PlatformDispatcher.instance.onError 与 runZonedGuarded

Mak*_*leg 9 dart flutter

任何人都可以解释(或提供解释文档的链接)何时必须使用 PlatformDispatcher.instance.onError 以及何时 runZonedGuarded ?据我了解,它们都是关于处理异步异常......

Umu*_*mut 3

更新(2023-07-04):

当前版本的非常好的 cli(截至撰写时为 0.15.0)未使用 runZonedGuarded。我认为双方都放弃了上述函数,因为它的用法很复杂,或者对 WidgetsFlutterBinding.ensureInitialized() 不友好。但这两种选择仍然有效。因此,正如原始答案中所述:

一如既往地进行自己的研究/测试,并根据您的需要选择选项。

原答案:

我正在寻找同一问题的答案,我想我已经找到了一个令人满意的答案:

选项 #1 PlatformDispatcher.instance.onError

https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/onError.html

来自https://firebase.google.com/docs/crashlytics/get-started?platform=flutter的示例

Future<void> main() async {
    WidgetsFlutterBinding.ensureInitialized();
    await Firebase.initializeApp();
    FlutterError.onError = (errorDetails) {
      FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
    };
    // Pass all uncaught asynchronous errors that aren't handled by the Flutter framework to Crashlytics
    PlatformDispatcher.instance.onError = (error, stack) {
      FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
      return true;
    };
    runApp(MyApp());

}
Run Code Online (Sandbox Code Playgroud)

但来自https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/instance.html的重要引用

考虑避免通过 PlatformDispatcher.instance 静态引用此单例,而更喜欢使用依赖项解析的绑定,例如 WidgetsBinding.instance.platformDispatcher。

该对象的静态访问意味着 Flutter 在测试中几乎没有选项来伪造或模拟给定对象。即使 Dart 提供特殊的语言结构来强制隐藏这些属性,这些机制也只对测试来说是合理的,而对于 Flutter 的未来来说它们是不合理的,因为我们在运行时合法地希望选择适当的实现。

WidgetsBinding.instance.platformDispatcher 唯一不合适的地方是,在通过调用 runApp() 或 WidgetsFlutterBinding.instance.ensureInitialized() 初始化绑定之前需要访问这些 API。在这种情况下,有必要(尽管不幸)静态使用 PlatformDispatcher.instance 对象。

选项 #2 runZonedGuarded

https://api.dart.dev/stable/2.18.7/dart-async/runZonedGuarded.html

我们还有另一个选项,就像您的问题一样,它在非常好的 cli 中使用。

Future<void> bootstrap(FutureOr<Widget> Function() builder) async {
  FlutterError.onError = (details) {
    log(details.exceptionAsString(), stackTrace: details.stack);
  };

  Bloc.observer = AppBlocObserver();

  await runZonedGuarded(
    () async => runApp(await builder()),
    (error, stackTrace) => log(error.toString(), stackTrace: stackTrace),
  );
}
Run Code Online (Sandbox Code Playgroud)

WidgetsFlutterBinding.ensureInitialized();不幸的是,如果您在方法之外使用,这将不起作用runZonedGuarded。所以记住这一点。一些问题链接:

https://github.com/firebase/flutterfire/issues/6964#issuecomment-915935180

https://github.com/flutter/flutter/issues/48972

结论

由于文档指出这种PlatformDispatcher.instance用法是不幸的,我想我们可以得出结论,使用runZonedGuarded是更好的选择。

一如既往地进行自己的研究/测试,并根据您的需要选择选项。