Flutter 异常处理

397 阅读1分钟

Dart单线程模型

2-21.eb7484c9.png

Dart 在单线程中是以消息循环机制来运行的,其中包含两个任务队列,一个是“微任务队列” microtask queue,另一个叫做“事件队列” event queue。微任务队列的执行优先级高于事件队列。
在事件循环中,当某个任务发生异常并没有被捕获时,程序并不会退出,而直接导致的结果是当前任务的后续代码就不会被执行了,也就是说一个任务中的异常是不会影响其他任务执行的

Flutter框架异常捕获

Flutter的异常分两类:同步异常和异步异常,同步异常可以通过try/catch捕获。

异步异常使用Zone.runZoned方法进行进行捕获。 Flutter使用 try {}catch(e,stack){}进行异常捕获。

同步异常

 try {
    built = build();
  } catch (e, stack) {
    // 有异常时则弹出错误提示  
    built = ErrorWidget.builder(_debugReportException('building $this', e, stack));
  } 
  
FlutterErrorDetails _debugReportException(
  String context,
  dynamic exception,
  StackTrace stack, {
  InformationCollector informationCollector
}) {
  //构建错误详情对象  
  final FlutterErrorDetails details = FlutterErrorDetails(
    exception: exception,
    stack: stack,
    library: 'widgets library',
    context: context,
    informationCollector: informationCollector,
  );
  //报告错误 
  FlutterError.reportError(details);
  return details;
}

通过_debugReportException发现使用FlutterError.reportError(details),进行异常上报。

处理flutter同步整体异常,在app入口的main方法中添加

FlutterError.onError = (FlutterErrorDetails details) {
  //获取所有同步异常,显示或者上报异常信息
};

异步异常处理

处理异步监听flutter同步整体异常,在app入口的main方法中添加Zone.runZoned。

我们可以给代码执行对象指定一个 Zone,在 Dart 中,Zone 表示一个代码执行的环境范围,其概念类似沙盒,不同沙盒之间是互相隔离的。如果我们想要观察沙盒中代码执行出现的异常,沙盒提供了 onError 回调函数,拦截那些在代码执行对象中的未捕获异常

runZoned(
  () => runApp(MyApp()),
  zoneSpecification: ZoneSpecification(
    // 拦截print
    print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
      collectLog(line);
      parent.print(zone, "Interceptor: $line");
    },
    // 拦截未处理的异步错误
    handleUncaughtError: (Zone self, ZoneDelegate parent, Zone zone,
                          Object error, StackTrace stackTrace) {
      reportErrorAndLog(details);
      parent.print(zone, '${error.toString()} $stackTrace');
    },
  ),
 );
 
 //或者使用
 //在Flutter开发通常使用此方法
runZonedGuarded(
    () {
      runApp(MyApp());
    },
    (error, stackTrace) {
      //没被我们catch的异常
      reportErrorAndLog(makeDetails(error, stackTrace));
    },
  );