当前位置: 首页 > Web前端 > HTML

Flutter异常监控-一-从

时间:2023-03-28 19:09:36 HTML

Zone开始如果你需要处理Flutter的异常捕获,那么恭喜你,你找对地方了。在这里我们从根源上为你准备了Flutter异常捕获的所有知识和原理,让你对FlutterZone的概念有更深刻的理解。什么是Zone///Zone代表了一个跨异步调用保持稳定的环境///SDK:代表了一个跨异步调用保持稳定的环境。通俗理解39|当线上出现问题时,如何做好异常捕获和信息收集工作?说明:我们可以为代码执行对象指定一个Zone。在Dart中,一个Zone代表一个代码执行的环境范围。它的概念类似于沙箱,不同的沙箱之间是相互隔离的。如果我们想在沙箱中观察代码执行中的异常,沙箱提供了onError回调函数来拦截代码执行对象中那些未捕获的异常。Zone创建Dart提供runZoned方法支持快速创建ZoneRrunZoned(Rbody(),{Map?zoneValues,ZoneSpecification?zoneSpecification,@Deprecated("UserunZonedGuardedinstead")Function?onError}){zoneValues:Zone的私有数据,可以通过实例zone[key]获取,可以理解为各个“沙盒”的私有数据。zoneSpecification:Zone的一些配置,可以自定义一些代码行为,比如拦截日志输出和错误等Zone函数捕获异常import'dart:async';//OUTPUT:Uncaughterror:Wouldnormallykilltheprogramvoidmain(){runZonedGuarded((){Timer.run((){throw'Wouldnormallykilltheprogram';});},(error,stackTrace){print('Uncaughterror:$error');});}同样既然trycatch是可以捕获的,为什么要通过Zone来捕获呢?Zone回调关闭异步捕获入口,提高可维护性。可以为您自动捕获意外未捕获的异常,以提高便利性。是否可以捕获所有异常?不行,只能处理case1。Zone默认的捕获范围主要是针对异步异常或者一般逻辑异常等常见异常。比如Future有问题,或者逻辑处理1/0,(见Tag3)。捕获异步异常的原理见简述-Flutter异常处理-掘金Dart中另外一个比较容易出现的异常是框架异常,比如构建异常,Zone无法捕获。原因参考Flutter异常捕获和Crash崩溃日志收集。如果想让Zone处理,可以这样抛(见Tag1)FlutterEngine和Native异常,isolate异常不在runZonedGuarded和FlutterError.onError可以处理的范围内。isolate异常处理原理(见Tag2)参考专播|温故知新,给大家说说专栏里那些并发Isolate异常无法被try-catch捕获的思考题。concurrentIsolate和mainIsolate之间的通信使用的是SendPort的消息机制,e??xception本质上也可以看做是一种消息传递机制。因此,主Isolate如果想捕获并发Isolate中的异常消息,可以将SendPort传递给并发Isolate。创建Isolate的函数spawn正好有一个SendPort类型的onError参数,所以concurrentIsolates可以向这个参数发送消息,实现异常通知。完整的Dart异常捕获代码};//Tag2Isolate.current.addErrorListener(RawReceivePort((dynamicpair)async{finalisolateError=pairasList;customerReport(details);}).sendPort,);runZoned(()=>runApp(MyApp()),zoneSpecification:ZoneSpecification(print:(Zoneself,ZoneDelegateparent,Zonezone,Stringline){report(line)},),onError:(Objectobj,StackTracestack){//标签3customerReport(e,stack);});}覆盖一组有限的方法,例如print()和scheduleMicrotask()main(){runZoned((){print("test");},zoneSpecification:ZoneSpecification(print:(self,parent,zone,s){parent.print(zone,"hookit:$s");}));}//OUTPUT:hookit:test上面的实现原理是什么?简单的说也就是说,runZoned从根区域派生出一个子区域。打印时,如果当前Zone不为空,则使用当前Zone的print进行打印,不使用根Zone的打印方法。具体参见Dart中Future、Zone、Timer的源码学习。执行诸如启动或停止计时器之类的操作,或者在代码进入或退出区域时保存堆栈跟踪。在下面的示例中,Zone提供了一个挂钩点。在执行方法时,可以进行额外的封装操作(Tag1,Tag2),比如打印耗时的方法,从而在不破坏原有代码的情况下实现非侵入式的统一逻辑注入。.import'dart:async';finaltotal=newStopwatch();finaluser=newStopwatch();finalspecification=ZoneSpecification(run:(self,parent,zone,f){//Tag1user.start();try{returnparent.run(zone,f);}finally{//Tag2user.stop();}});voidmain(){runZoned((){total.start();a();b();c().then((_){print(total.elapsedMilliseconds);print(user.elapsedMilliseconds);});},zoneSpecification:specification);}voida(){打印('a');}voidb(){print('b');}Futurec(){returnFuture.delayed(Duration(seconds:5),()=>print('c'));}输出:abc50056将数据(称为区域本地值)与其他区域相关联。这个功能类似于java中的threadlocal。每个Zone都相当于自己取值的范围。Zone的直接价值的传递和分享是通过zonevalue来实现的。import'dart:async';voidmain(){ZonefirstZone=Zone.current.fork(zoneValues:{"name":"bob"});区域secondZone=firstZone.fork(zoneValues:{"extra_values":12345});secondZone.run((){print(secondZone["name"]);//bobprint(secondZone["extra_values"]);//12345});}案例说明:类似Linux,当Zone做forking时,parentZone持有的ZoneSpecification和ZoneValues会被继承,可以直接使用。并且支持添加,secondZone在firstZone的基础上,增加了extra_values属性,不会因为secondZone的ZoneValues而替换name属性。如果您觉得文章对您有帮助,点赞,收藏,关注,评论,一键四连支持,您的支持就是我创作最大的动力。??欢迎关注公众号:编程黑板报原创技术文章,第一时间推送处理-掘金】(https://juejin.cn/post/712163...)2.8Flutter异常捕获|