如果你正须要解决Flutter异样捕捉,那么祝贺你,找对地了,这里从本源上给你筹备了Flutter异样捕捉须要是所有常识和原理,让你更粗浅意识Flutter Zone概念。
Zone是什么
/// A zone represents an environment that remains stable across asynchronous
/// calls.
SDK中形容:示意一个环境,这个环境为了保持稳定异步调用。
艰深了解39 | 线上呈现问题,该如何做好异样捕捉与信息采集?中形容:
咱们能够给代码执行对象指定一个 Zone,在 Dart 中,Zone 示意一个代码执行的环境范畴,其概念相似沙盒,不同沙盒之间是相互隔离的。如果咱们想要察看沙盒中代码执行呈现的异样,沙盒提供了 onError 回调函数,拦挡那些在代码执行对象中的未捕捉异样。
Zone创立
Dart提供了runZoned办法,反对Zone的疾速创立
R runZoned<R>(R body(),
{Map<Object?, Object?>? zoneValues,
ZoneSpecification? zoneSpecification,
@Deprecated("Use runZonedGuarded instead") Function? onError}) {
zoneValues
: Zone 的公有数据,能够通过实例zone[key]
获取,能够了解为每个“沙箱”的公有数据。zoneSpecification
:Zone的一些配置,能够自定义一些代码行为,比方拦挡日志输入和谬误等
Zone的作用
捕捉异样
import 'dart:async';
//OUTPUT:Uncaught error: Would normally kill the program
void main() {
runZonedGuarded(() {
Timer.run(() {
throw 'Would normally kill the program';
});
}, (error, stackTrace) {
print('Uncaught error: $error');
});
}
用try catch一样能够捕捉,为啥要通过Zone来捕捉?
- Zone回调收拢了异步捕捉入口,进步了可维护性。
- 未意料的未捕捉异样能够帮你主动捕捉到,进步便捷性。
是不是所有异样都能够捕捉到?
不是, 只能解决状况1。
- Zone默认捕捉范畴次要针对异步异样或者个别逻辑异样等惯例异样,比方Future中出了问题,或者逻辑解决了1/0,(见Tag3),捕捉异步异样原理见简话-Flutter异样解决 – 掘金
- Dart中另外比拟容易呈现的异样是framework异样,比方build异样等,这种异样Zone无奈捕捉到,起因能够参看Flutter异样捕捉和Crash解体日志收集 。如果想Zone来解决可这样抛给它(见Tag1)
- Flutter Engine和Native异样,isolate异样 不是runZonedGuarded和FlutterError.onError 能解决范畴。
-
isolate异样解决(见Tag2)
原理参考特地放送 | 温故而知新,与你说说专栏的那些思考题
并发 Isolate 的异样是无奈通过 try-catch 来捕捉的。并发 Isolate 与主 Isolate 通信是采纳 SendPort 的音讯机制,而异样实质上也能够视作一种消息传递机制。所以,如果主 Isolate 想要捕捉并发 Isolate 中的异样音讯,能够给并发 Isolate 传入 SendPort。而创立 Isolate 的函数 spawn 中就恰好有一个类型为 SendPort 的 onError 参数,因而并发 Isolate 能够通过往这个参数里发送音讯,实现异样告诉。
残缺Dart异样捕捉代码
void main() {
FlutterError.onError = (FlutterErrorDetails details) {
Zone.current.handleUncaughtError(details.exception, details.stack);//Tag1
//或customerReport(details);
};
//Tag2
Isolate.current.addErrorListener(
RawReceivePort((dynamic pair) async {
final isolateError = pair as List<dynamic>;
customerReport(details);
}).sendPort,
);
runZoned(
() => runApp(MyApp()),
zoneSpecification: ZoneSpecification(
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
report(line)
},
),
onError: (Object obj, StackTrace stack) {
//Tag3
customerReport(e, stack);
}
);
}
在局部或全副代码中笼罩一组无限的办法
例如print()
和scheduleMicrotask()
main() {
runZoned(() {
print("test");
}, zoneSpecification: ZoneSpecification(
print: (self, parent, zone, s) {
parent.print(zone, "hook it: $s");
}
));
}
//OUTPUT:hook it: test
下面实现的原理是什么呢?
简略讲就是runZoned从root Zone fork了一个子Zone,print打印时如果以后Zone
不为空则应用以后Zone的print来打印,而不应用root Zone的print办法。具体见Dart中Future、Zone、Timer的源码学习
每次代码进入或退出区域时执行一个操作
例如启动或进行计时器,或保留堆栈跟踪。
如下例子,Zone提供了一个hook点,在执行其中办法时候,能够做额定包装操作(Tag1,Tag2),比方耗时办法打印,这样在不毁坏原有代码根底上实现了无侵入的对立逻辑注入。
import 'dart:async';
final total = new Stopwatch();
final user = new Stopwatch();
final specification = ZoneSpecification(run: <R>(self, parent, zone, f) {
//Tag1
user.start();
try {
return parent.run(zone, f);
} finally {
//Tag2
user.stop();
}
});
void main() {
runZoned(() {
total.start();
a();
b();
c().then((_) {
print(total.elapsedMilliseconds);
print(user.elapsedMilliseconds);
});
}, zoneSpecification: specification);
}
void a() {
print('a');
}
void b() {
print('b');
}
Future<void> c() {
return Future.delayed(Duration(seconds: 5), () => print('c'));
}
输入:
a
b
c
5005
6
将数据(称为 Zone本地值)与各个其余Zone相关联
这个作用相似java中的threadlocal,每个Zone相当于有本人值的作用范畴,Zone间接值的传递和共享通过zonevalue来实现。
import 'dart:async';
void main() {
Zone firstZone = Zone.current.fork(zoneValues: {"name": "bob"});
Zone secondZone = firstZone.fork(zoneValues: {"extra_values": 12345});
secondZone.run(() {
print(secondZone["name"]); // bob
print(secondZone["extra_values"]); // 12345
});
}
案例阐明:
和Linux相似地,当Zone做Fork的时候,会将父Zone所持有的ZoneSpecification、ZoneValues会继承下来,能够间接应用。并且是反对追加的,secondZone在firstZone的根底之上,又追加了
extra_values
属性,不会因为secondZone的ZoneValues就导致name属性被替换掉。
如果感觉文章对你有帮忙,点赞、珍藏、关注、评论,一键四连反对,你的反对就是我创作最大的能源。
❤️ 欢送关注公众号:码里特地有禅 原创技术文章第一工夫推送 ❤️
参考链接
简话-Flutter异样解决 – 掘金
Zones | Dart
Brian Ford – Zones – NG-Conf 2014 – YouTube
[[Flutter] 意识Zone和异样解决 – 掘金](https://juejin.cn/post/712163…)
2.8 Flutter异样捕捉 | 《Flutter实战·第二版》
特地放送 | 温故而知新,与你说说专栏的那些思考题
发表回复