);
输出结果:
class Custom_exception_Name implements Exception {
// can contain constructors, variables and methods
class AmtException implements Exception {
String errMsg() => 'Amount should be greater than zero';
throw new AmtException();
2、异步异常
try-catch 代码块不能捕获到异步异常,使用 await 关键字声明的同步调用,属于同步异常范围,可以通过 try-catch 捕获。
使用 catchError 捕获异步异常,第一个参数为 Function error 类型,第二个参数为 {bool test(Object error)},是一个判断表达式,当此表达式返回值为 true 时,表示需要执行 catch 逻辑,如果返回 false,则不执行 catch 逻辑,即会成为未捕获的异常,默认不传时 认为是true。
这里的作用是可以精细化的处理异常,可以理解为同步异常中强化版的 on 关键字,
入参至多两个 分别为error 和 stack,均可选。
Future(() {
}).then((value){
}).catchError((error, stack) {
Future.delayed(Duration(seconds: 1)).then((e) => Future.error("xxx"));
二、Flutter异常捕获、抛出
为了捕获并上报异常,可以把应用运行在一个自定义的 Zone 里面。 Zones 为代码建立执行上下文环境。在这个上下文环境中,所有发生的异常在抛出 onError 时都能够很容易地被捕获到。
Dart中有一个runZoned(...) 方法,可以给执行对象指定一个Zone。Zone表示一个代码执行的环境范围,为了方便理解,读者可以将Zone类比为一个代码执行沙箱,不同沙箱的之间是隔离的,沙箱可以捕获、拦截或修改一些代码行为,如Zone中可以捕获日志输出、Timer创建、微任务调度的行为,同时Zone也可以捕获所有未处理的异常。下面我们看看runZoned(...)方法定义:
R runZoned<R>(R body(), {
Map zoneValues,
ZoneSpecification zoneSpecification,
Function onError,
参数含义可参考《Flutter实战》https://book.flutterchina.club/chapter2/thread_model_and_error_report.html
在下面的例子中,将会把应用运行在一个新的 Zone 里面并捕获所有错误,在 1.17 之前的 Flutter 版本里,你可以通过 onError() 回调捕获所有的异常。
runZoned<Future<void>>(() async {
runApp(MyApp());
}, onError: (error, stackTrace) {
// Whenever an error occurs, call the `_reportError` function. This sends
// Dart errors to the dev console or Sentry depending on the environment.
_reportError(error, stackTrace);
在包含了 Dart 2.8 的 Flutter 1.17 中,使用 runZonedGuarded:
runZonedGuarded<Future<void>>(() async {
runApp(MyApp());
}, (Object error, StackTrace stackTrace) {
// Whenever an error occurs, call the `_reportError` function. This sends
// Dart errors to the dev console or Sentry depending on the environment.
_reportError(error, stackTrace);
除了 Dart 异常,Flutter 也能抛出其他的异常,比如调用原生代码发生的平台异常。这种类型的异常也同样是需要上报的。
为了捕获 Flutter 异常,需要重写 FlutterError.onError 属性。在开发环境下,可以将异常格式化输出到控制台。在生产环境下,可以把异常传递给上个步骤中的 onError 回调。
大致步骤如下:
Future<Null> main() async {
//重写FlutterError.onError
FlutterError.onError = (FlutterErrorDetails details) {
if (isInDebugMode) {
// In development mode, simply print to console.
FlutterError.dumpErrorToConsole(details);
} else {
// In production mode, report to the application zone to report to
// Sentry.
Zone.current.handleUncaughtError(details.exception, details.stack);
//使用runZonedGuarded捕获日志输出、Timer创建、微任务调度的行为、所有未处理的异常
runZonedGuarded<Future<Null>>(
() async {
runApp(MyApp());
(error, stackTrace) async {
await _reportErrorAndLog(error, stackTrace);
zoneSpecification: ZoneSpecification(
print: (Zone self, ZoneDelegate parent, Zone zone, String line) async {
await collectLog(line); // 收集日志
Future<Null> collectLog(String line) async {
//收集日志
//上报错误和日志逻辑
Future<Null> _reportErrorAndLog(dynamic error, dynamic stackTrace) async {
print('Caught error: $error');
if (isInDebugMode) {
print(stackTrace);
print('In dev mode. Not sending report to Sentry.io.');
return;
//TODO: response 为上传请求结果
if (response.isSuccessful) {
print('Success!');
} else {
print('Failed to report to Sentry.io: ${response}');
//判断debug及release环境
bool get isInDebugMode {
bool inDebugMode = false;
assert(inDebugMode = true);
return inDebugMode;
https://book.flutterchina.club/chapter2/thread_model_and_error_report.html
https://flutter.cn/docs/cookbook/maintenance/error-reporting#5-catch-and-report-dart-errors
https://juejin.cn/post/6906274131394691085