在 Flutter 里处理错误
Flutter 框架可以捕获运行期间的错误,包括构建期间、布局期间和绘制期间。
所有 Flutter 的错误均会被回调方法 FlutterError.onError
捕获。默认情况下,会调用 FlutterError.presentError
方法,并将错误转储到当前的设备日志中。当从 IDE 运行应用时,检查器重写了该方法,错误也被发送到 IDE 的控制台,可以在控制台中检查出错的对象。
当构建期间发生错误时,回调函数 ErrorWidget.builder
会被调用,来生成一个新的 widget,用来代替构建失败的 widget。默认情况,debug 模式下会显示一个红色背景的错误页面,
release 模式下会展示一个灰色背景的空白页面。
如果在调用堆栈上没有 Flutter 回调的情况下发生错误,它们由发生区域的 Zone
处理。
Zone
在默认情况下仅会打印错误,而不会执行其他任何操作。
这些回调方法都可以被重写,通常在 void main()
方法中重写。
下面解释了所有的错误捕获类型。在最后的代码段可以用于处理所有类型的错误。尽管你可以直接复制粘贴代码段,但我们建议你先了解每种错误类型。
Flutter 导致的错误
#例如,如果你想在 release 模式下发生错误时立刻关闭应用,可以使用下面的回调方法:
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
FlutterError.onError = (details) {
FlutterError.presentError(details);
if (kReleaseMode) exit(1);
};
runApp(const MyApp());
}
// The rest of the `flutter create` code...
这个回调方法也可以上报错误到日志服务平台。更多信息可以查看文档 报错信息通过服务上传。
自定义一个 ErrorWidget 以展示 build 时的错误
#定义一个自定义的 error widget,以当 builder 构建 widget 失败时显示,请使用 MaterialApp.builder
。
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
builder: (context, widget) {
Widget error = const Text('...rendering error...');
if (widget is Scaffold || widget is Navigator) {
error = Scaffold(body: Center(child: error));
}
ErrorWidget.builder = (errorDetails) => error;
if (widget != null) return widget;
throw StateError('widget is null');
},
);
}
}
未被 Flutter 捕获的错误
#假设一个 onPressed
回调调用了异步方法,例如 MethodChannel.invokeMethod
(或者其他 plugin 的方法):
OutlinedButton(
child: const Text('Click me!'),
onPressed: () async {
const channel = MethodChannel('crashy-custom-channel');
await channel.invokeMethod('blah');
},
)
如果 invokeMethod
抛出了错误,它不会传递至 FlutterError.onError
,而是直接进入 runApp
的 Zone
。
如果你想捕获这样的错误,请使用 PlatformDispatcher.instance.onError
。
import 'package:flutter/material.dart';
import 'dart:ui';
void main() {
MyBackend myBackend = MyBackend();
PlatformDispatcher.instance.onError = (error, stack) {
myBackend.sendError(error, stack);
return true;
};
runApp(const MyApp());
}
处理所有类型的错误
#如果你想在异常抛出时退出应用,并在 build 错误时展示自定义的 ErrorWidget,你可以在下面的代码片段的基础上定制你的处理:
import 'package:flutter/material.dart';
import 'dart:ui';
Future<void> main() async {
await myErrorsHandler.initialize();
FlutterError.onError = (details) {
FlutterError.presentError(details);
myErrorsHandler.onErrorDetails(details);
};
PlatformDispatcher.instance.onError = (error, stack) {
myErrorsHandler.onError(error, stack);
return true;
};
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
builder: (context, widget) {
Widget error = const Text('...rendering error...');
if (widget is Scaffold || widget is Navigator) {
error = Scaffold(body: Center(child: error));
}
ErrorWidget.builder = (errorDetails) => error;
if (widget != null) return widget;
throw StateError('widget is null');
},
);
}
}
除非另有说明,本文档之所提及适用于 Flutter 的最新稳定版本,本页面最后更新时间: 2024-07-03。 查看文档源码 或者 为本页面内容提出建议。