Flutter 中的错误处理
Flutter 框架会捕获由框架本身触发的回调过程中发生的错误,包括在构建、布局和绘制阶段遇到的错误。不在 Flutter 回调中的错误无法被框架捕获,但您可以通过在 PlatformDispatcher
上设置错误处理程序来处理它们。
所有被 Flutter 捕获的错误都会被路由到 FlutterError.onError
处理程序。默认情况下,这会调用 FlutterError.presentError
,它会将错误转储到设备日志中。从 IDE 运行时,检查器会覆盖此行为,以便错误也可以被路由到 IDE 的控制台,让您可以检查消息中提到的对象。
当在构建阶段发生错误时,会调用 ErrorWidget.builder
回调来构建将用于替换失败的小部件的小部件。默认情况下,在调试模式下,这会显示一个红色的错误消息,而在发布模式下,它会显示一个灰色的背景。
当出现没有 Flutter 回调在调用堆栈中的错误时,它们由 PlatformDispatcher
的错误回调处理。默认情况下,这只会打印错误,不做其他任何事情。
您可以自定义这些行为,通常是在您的 void main()
函数中设置它们的值。
下面对每种错误类型的处理进行了说明。底部有一个处理所有类型错误的示例代码片段。尽管您可以直接复制粘贴此代码片段,但我们建议您首先熟悉每种错误类型。
Flutter 捕获的错误
#例如,要在发布模式下使您的应用程序在捕获到 Flutter 错误时立即退出,您可以使用以下处理程序:
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...
此处理程序也可用于将错误报告给日志记录服务。有关更多详细信息,请参阅我们的 错误报告到服务 食谱章节。
为构建阶段错误定义自定义错误小部件
#要定义一个自定义错误小部件,该小部件将在构建器无法构建小部件时显示,请使用 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
(或几乎任何插件)。例如:
OutlinedButton(
child: const Text('Click me!'),
onPressed: () async {
const channel = MethodChannel('crashy-custom-channel');
await channel.invokeMethod('blah');
},
)
如果 invokeMethod
引发错误,它不会被转发到 FlutterError.onError
。相反,它会被转发到 PlatformDispatcher
。
要捕获此类错误,请使用 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());
}
处理所有类型的错误
#假设您想在任何异常发生时退出应用程序,并在构建器小部件失败时显示自定义错误小部件 - 您可以基于以下代码片段处理您的错误:
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');
},
);
}
}