Flutter中FlutterError.onError和PlatformDispatcher.instance.onError的区别

Boo*_*unz 7 error-handling dart dart-async flutter flutter-platform-channel

假设在 Flutter 应用程序中,我们希望在顶层捕获任何未捕获的异常/错误,因此我们按照文档执行此操作:

main() {
  
  // All uncaught errors thrown from synchronous code blocks will end up here:
  FlutterError.onError = (FlutterErrorDetails details) {
    MyLogger.instance.logUncaughtErrorSync(details);
  };

  // All uncaught errors thrown from async code blocks will end up here:
  PlatformDispatcher.instance.onError = (Object error, StackTrace stack) {
    MyLogger.instance.logUncaughtErrorASync(error, stack);
    return true;
  };
  
  runApp(const MyApp());
Run Code Online (Sandbox Code Playgroud)

虽然文档似乎暗示两者之间的区别在于错误是否源自 Dart(特别是“Flutter”)代码与平台(Android/IOS)代码,但通过我的测试,我可以看出两者之间的唯一区别是对象(错误)是否是从异步或同步 Dart 代码中抛出的。

例如,如果在Dart代码(不是平台代码)中,我们只需输入:

_function() async {
    throw('error');
}
Run Code Online (Sandbox Code Playgroud)

我们称之为该函数,它将通过“平台调度程序”冒泡并被视为“平台错误”,但似乎只是因为它发生在后台线程上?

实际上似乎没有任何机制允许从 Java 或 Swift 代码抛出异常来触发这些 onError 函数。

但肯定不止于此,那么拥有两种独立的机制(具有不同的输入——FlutterErrorDetails 与 Object+StackTrace)有什么意义……真正的区别是什么?

mko*_*lys 2

事实上,您引用的文档页面中提供了答案。

FlutterError.onError适用于 Flutter 框架错误 - 在框架级别发生的错误(在构建、布局和绘制阶段遇到的错误)。简而言之,如果您因编写的 Dart 代码或 Flutter 框架中的代码而发生错误,则会转到FlutterError.onError.

另一方面,PlatformDispatcher.instance.onError它是针对平台级错误的。如您所知,Flutter 支持多个平台,并且这些平台在其本机层执行代码。例如,您使用插件或使用平台通道实现自己的 Flutter 插件代码:

OutlinedButton(
  child: const Text('Click me!'),
  onPressed: () async {
    const channel = MethodChannel('crashy-custom-channel')
    await channel.invokeMethod('blah')
  },
)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,这不再是 Flutter 级别的错误,因此它将被转发到PlatformDispatcher.instance.onError.

  • 是的,这也是我最初的理解,因为他们使用的命名和他们给出的示例,但是经过测试后,似乎它与错误的性质没有任何关系,仅与错误是否发生在同步 dart 代码与异步飞镖代码。例如,在该按钮中,您可以使用 onPressed: () async { throw “poo”;} ,但它仍然是“平台错误” (3认同)