简介:利用性能稳固是良好用户体验中十分要害的一环,为了更好保障利用性能稳固,异样捕捉在保障线上产品稳固中扮演着至关重要的角色。咱们团队在推出了U-APM挪动利用性能监控的产品后,帮忙开发者定位并解决掉很多线上的疑难杂症。随着应用人数的增多,关注度的进步,在访问客户和开发者的留言中,很多开发者都提出心愿该产品能够反对flutter框架的异样捕捉。自身我并没有做过flutter开发,所以次要是通过在现有产品能力根底上做插件实现异样的上报,这篇文章就记录我学习flutter错误处理的过程和遇到的问题。

作者:友盟+技术专家 彦克

一、背景

利用性能稳固是良好用户体验中十分要害的一环,为了更好保障利用性能稳固,异样捕捉在保障线上产品稳固中扮演着至关重要的角色。咱们团队在推出了U-APM挪动利用性能监控的产品后,帮忙开发者定位并解决掉很多线上的疑难杂症。随着应用人数的增多,关注度的进步,在访问客户和开发者的留言中,很多开发者都提出心愿该产品能够反对flutter框架的异样捕捉。自身我并没有做过flutter开发,所以次要是通过在现有产品能力根底上做插件实现异样的上报,这篇文章就记录我学习flutter错误处理的过程和遇到的问题。

二、Flutter异样

Flutter 异样指的是,Flutter 程序中 Dart 代码运行时意外产生的谬误事件。

三、Flutter异样特点

Dart是单过程机制,所以在这个过程中呈现问题时仅仅会影响以后过程,Dart 采纳事件循环的机制来运行工作,当某个工作产生异样并没有被捕捉时,程序并不会退出,而间接导致的后果是当前任务的后续代码就不会被执行了,也就是说一个工作中的异样是不会影响其它工作执行的,各个工作的运行状态是相互独立的。

如:咱们能够通过与 Java 相似的 try-catch 机制来捕捉它。但与 Java 不同的是,Dart 程序不强制要求咱们必须解决异样。

四、Flutter异样分类

在Flutter开发中,依据异样起源的不同,能够将异样分为Framework异样和App异样。Flutter对这两种异样提供了不同的捕捉形式,Framework异样是由Flutter框架引发的异样,通常是因为谬误的利用代码造成Flutter框架底层的异样判断引起的。而对于App异样,就是利用代码的异样,通常由未解决应用层其余模块所抛出的异样引起。依据异样代码的执行时序,App 异样能够分为两类,即同步异样和异步异样。

五、捕捉形式

1.App 异样的捕捉形式

捕捉同步异样应用try-catch 机制:

// 应用 try-catch 捕捉同步异样try {  throw StateError('This is a Dart exception.');}catch(e) {  print(e);}

捕捉异步异样应用Future 提供的 catchError 语句:

// 应用 catchError 捕捉异步异样Future.delayed(Duration(seconds: 1))    .then((e) => throw StateError('This is a Dart exception in Future.'))    .catchError((e)=>print(e));

看到这里预计很多人心里会问,就不能有一种形式既能够监控同步又能够监控异步异样吗?

答案是有的。

Flutter 提供了 Zone.runZoned 办法来治理代码中的所有异样。咱们能够给代码执行对象指定一个Zone,在 Dart 中,Zone 示意一个代码执行的环境范畴,其概念相似沙盒,不同沙盒之间是相互隔离的。如果咱们想要察看沙盒中代码执行呈现的异样,沙盒提供了 onError 回调函数,拦挡那些在代码执行对象中的未捕捉异样。废话不多说,

Show me the code!runZoned(() {  // 同步异样  throw StateError('This is a Dart exception.');}, onError: (dynamic e, StackTrace stack) {  print('Sync error caught by zone');});runZoned(() {  // 异步异样  Future.delayed(Duration(seconds: 1))      .then((e) => throw StateError('This is a Dart exception in Future.'));}, onError: (dynamic e, StackTrace stack) {  print('Async error aught by zone');});

为了可能集中捕捉 Flutter 利用中的未解决异样,最终我把main函数中的 runApp 语句也搁置在 Zone 中。这样在检测到代码中运行异样时,就能依据获取到的异样上下文信息,进行对立解决了:

runZoned>(() async {  runApp(MyApp());}, onError: (error, stackTrace) async { //Do sth for error});

2.Framework异样捕捉形式

Flutter 框架为咱们在很多要害的办法进行了异样捕捉。如果咱们想本人上报异样,只须要提供一个自定义的错误处理回调即可,如:

void main() {  FlutterError.onError = (FlutterErrorDetails details) {    reportError(details);  }; ...}

有没有一套从天而降的代码,可能对立解决以上异样呢?

3.总结(一套代码捕捉所有异样)

runZonedGuarded(() async {    WidgetsFlutterBinding.ensureInitialized();FlutterError.onError = (FlutterErrorDetails details) {      myErrorsHandler.onError(details.exception,details.stack);    };    runApp(MyApp());  }, (Object error, StackTrace stack) {    myErrorsHandler.onError(error, stack);  });

代码中呈现了一句,上诉从没有呈现过的代码即WidgetsFlutterBinding.ensureInitialized(),当我把这行代码正文掉的时候,框架异样是捕捉不到的。

过后困扰了良久最初终于查到了起因:

上图是Flutter的架构层,WidgetFlutterBinding用于与 Flutter 引擎交互。 咱们的APM产品须要调用 native 代码来初始化,并且因为插件须要应用平台 channel 来调用 native 代码,这是异步实现的,因而必须调用ensureInitialized()确保你有一个 WidgetsBinding 的实例.

来自 docs :

Returns an instance of the WidgetsBinding, creating and initializing it if necessary. If one is created, it will be a WidgetsFlutterBinding. If one was previously initialized, then it will at least implement WidgetsBinding.

注:如果你的利用在runApp 中调用了 WidgetsFlutterBinding.ensureInitialized() 办法来进行一些初始化操作,则必须在runZonedGuarded中调用WidgetsFlutterBinding.ensureInitialized()

六、异样上报

异样上报的整体计划是通过已有的插件减少接口,桥接Android APM 和 iOS APM库的自定义异样上报接口。

插件减少函数

static void postException(error, stack) {    List args = [error,stack];    //将异样和堆栈上报至umapm    _channel.invokeMethod("postException",args);  }

Android 端调用自定义异样上报:

private void postException(List args){    String error = (String)args.get(0);    String stack = (String)args.get(1);    UMCrash.generateCustomLog(stack,error);  }

iOS端调用自定义异样上报:

if ([@"postException" isEqualToString:call.method]){        NSString* error = arguments[0];        NSString* stack = arguments[1];        [UMCrash reportExceptionWithName:@"Flutter" reason:error stackTrace:stack terminateProgram:NO]; }

以上就是本期干货内容的介绍,心愿咱们的技术内容能够更好地帮忙开发者们解决问题,咱们将陪伴开发者们一起提高,一起成长。

原文链接
本文为阿里云原创内容,未经容许不得转载。