赞
踩
try/catch/finally
来捕获代码块异常,这个和其它编程语言类似。Flutter 框架在很多关键的方法进行了异常捕获。
@override
void performRebuild() {
try {
//执行build方法
built = build();
} catch (e, stack) {
// 有异常时则弹出错误提示
built = ErrorWidget.builder(_debugReportException('building $this', e, stack));
}
}
可以看到,在发生异常时,Flutter默认的处理方式是弹一个ErrorWidget
_debugReportException()
方法看看: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; }
发现,错误是通过FlutterError.reportError
方法上报的,继续跟踪
static void reportError(FlutterErrorDetails details) {
...
if (onError != null)
onError(details); //调用了onError回调
}
onError
是FlutterError
的一个静态属性,它有一个默认的处理方法 dumpErrorToConsole
,到这里就清晰了,如果想自己上报异常,只需要提供一个自定义的错误处理回调即可,如: void main() {
FlutterError.onError = (FlutterErrorDetails details) {
reportError(details);
};
...
}
在Flutter中,还有一些Flutter没有为我们捕获的异常,如调用空对象方法异常、Future中的异常。
try/catch
捕获,而异步异常则比较麻烦,如下面的代码是捕获不了Future
的异常的:try{
Future.delayed(Duration(seconds: 1)).then((e) => Future.error("xxx"));
}catch (e){
print(e)
}
Dart中有一个runZoned(...)
方法,可以给执行对象指定一个Zone。
runZoned(...)
方法定义:R runZoned<R>(R body(), {
Map zoneValues,
ZoneSpecification zoneSpecification,
Function onError,
})
zone[key]
获取,可以理解为每个“沙箱”的私有数据。下面是拦截应用中所有调用print
输出日志的行为。
main() {
runZoned(() => runApp(MyApp()), zoneSpecification: new ZoneSpecification(
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
parent.print(zone, "Intercepted: $line");
}),
);
}
print
方法输出日志的行为都会被拦截,通过这种方式,也可以在应用中记录日志,等到应用触发未捕获的异常时,将异常信息和日志统一上报。ZoneSpecification还可以自定义一些其他行为,读者可以查看API文档。onError:Zone中未捕获异常处理回调,如果开发者提供了onError回调或者通过ZoneSpecification.handleUncaughtError
指定了错误处理回调,那么这个zone将会变成一个error-zone,该error-zone中发生未捕获异常(无论同步还是异步)时都会调用开发者提供的回调,如:
runZoned(() {
runApp(MyApp());
}, onError: (Object obj, StackTrace stack) {
var details=makeDetails(obj,stack);
reportError(details);
});
结合上面的FlutterError.onError
就可以捕获我们Flutter应用中全部错误了!需要注意的是,error-zone内部发生的错误是不会跨越当前error-zone的边界的,如果想跨越error-zone边界去捕获异常,可以通过共同的“源”zone来捕获,如:
var future = new Future.value(499);
runZoned(() {
var future2 = future.then((_) { throw "error in first error-zone"; });
runZoned(() {
var future3 = future2.catchError((e) { print("Never reached!"); });
}, onError: (e) { print("unused error handler"); });
}, onError: (e) { print("catches error of first error-zone."); });
void collectLog(String line){ ... //收集日志 } void reportErrorAndLog(FlutterErrorDetails details){ ... //上报错误和日志逻辑 } FlutterErrorDetails makeDetails(Object obj, StackTrace stack){ ...// 构建错误信息 } void main() { FlutterError.onError = (FlutterErrorDetails details) { reportErrorAndLog(details); }; runZoned( () => runApp(MyApp()), zoneSpecification: ZoneSpecification( print: (Zone self, ZoneDelegate parent, Zone zone, String line) { collectLog(line); // 收集日志 }, ), onError: (Object obj, StackTrace stack) { var details = makeDetails(obj, stack); reportErrorAndLog(details); }, ); }
## 最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓
PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。