Flutter中的异常处理有哪些?

Flutter 的异常处理机制包括 同步异常异步异常 ,涉及多个层面,如 Dart 语言级别的异常捕获Flutter 框架的错误处理机制自定义异常处理 以及 错误上报


1. Dart 语言级别的异常处理

Dart 主要使用 try-catch 进行异常捕获,并区分 同步异常异步异常 的处理方式。

1.1. 同步异常

同步代码中的异常可以通过 try-catch 捕获:

php 复制代码
dart
复制编辑
void main() {
  try {
    int result = 10 ~/ 0; // 除以 0,会触发异常
  } catch (e, stackTrace) {
    print("捕获异常: $e");
    print("堆栈信息: $stackTrace");
  }
}
  • e 捕获异常对象
  • stackTrace 获取异常发生的堆栈信息,方便调试

常见异常类型:

  • FormatException:数据格式错误
  • RangeError:数组越界
  • TypeError:类型转换错误
  • StateError:非法状态操作
  • ArgumentError:参数错误

1.2. 异步异常

Flutter 使用 异步编程(Future 和 Stream) ,因此要特别注意 FutureStream 的异常处理。

1.2.1. Future 异常处理

异步 Future 任务的异常需要使用 .catchError()try-catch 捕获:

csharp 复制代码
dart
复制编辑
Future<void> asyncTask() async {
  try {
    await Future.delayed(Duration(seconds: 1));
    throw Exception("异步任务异常");
  } catch (e) {
    print("捕获 Future 异常: $e");
  }
}

void main() {
  asyncTask();
}

另一种方式是 .catchError()

javascript 复制代码
dart
复制编辑
Future<void> asyncTask() {
  return Future.delayed(Duration(seconds: 1))
      .then((_) => throw Exception("异步任务异常"))
      .catchError((e) {
        print("Future 捕获异常: $e");
      });
}

1.2.2. Stream 异常处理

Stream 中的异常不会自动抛出,需要使用 handleError()try-catch 捕获:

dart 复制代码
dart
复制编辑
void main() {
  Stream<int> stream = Stream.periodic(Duration(seconds: 1), (count) {
    if (count == 2) throw Exception("Stream 发生错误");
    return count;
  }).take(5);

  stream.listen(
    (data) => print("收到数据: $data"),
    onError: (error) => print("捕获 Stream 异常: $error"),
  );
}

2. Flutter 框架级别的异常处理

Flutter 提供了一套全局异常处理机制,包括:

  • FlutterError.onError
  • PlatformDispatcher.instance.onError
  • runZonedGuarded

2.1. 处理 Flutter 框架错误 (FlutterError.onError)

Flutter 框架内部的异常(例如 setState() 期间的异常)会由 FlutterError.onError 处理:

scss 复制代码
dart
复制编辑
void main() {
  FlutterError.onError = (FlutterErrorDetails details) {
    print("Flutter 框架错误: ${details.exception}");
    print("错误详情: ${details.stack}");
  };

  runApp(MyApp());
}

应用场景

  • 捕获 UI 相关异常,如 build() 方法中的错误
  • 处理 Flutter 框架错误

2.2. 捕获 Native 层异常 (PlatformDispatcher.instance.onError)

PlatformDispatcher.instance.onError 可用于捕获 Flutter Engine 层的异常:

arduino 复制代码
dart
复制编辑
void main() {
  PlatformDispatcher.instance.onError = (error, stack) {
    print("捕获 Native 层异常: $error");
    return true; // 阻止异常冒泡
  };

  runApp(MyApp());
}

适用场景

  • 处理 Dart 代码未捕获的异常
  • 监听 Native 层的异常信息

2.3. 捕获 runZonedGuarded 异常

Dart 允许在 runZonedGuarded 中执行代码,确保 FutureStream 中的异常不会导致程序崩溃:

scss 复制代码
dart
复制编辑
void main() {
  runZonedGuarded(() {
    runApp(MyApp());
  }, (error, stackTrace) {
    print("runZonedGuarded 捕获到异常: $error");
  });
}

适用场景

  • 全局捕获 Future 异常
  • 防止异常导致 App 崩溃
  • 统一上报异常

3. 统一异常上报

在生产环境中,异常通常需要上报到日志系统(如 Sentry、Firebase Crashlytics)。

3.1. 结合 FlutterError.onError 进行上报

scss 复制代码
dart
复制编辑
void main() {
  FlutterError.onError = (FlutterErrorDetails details) {
    // 发送错误信息到服务器
    reportError(details.exception, details.stack);
  };

  runApp(MyApp());
}

void reportError(Object error, StackTrace? stack) {
  // 发送到 Sentry 或 Firebase
  print("上报错误: $error");
}

4. Widget 层面的异常捕获

有时,我们希望在 UI 层面防止崩溃,比如 build() 发生异常时显示默认 UI。

4.1. 使用 ErrorWidget

Flutter 允许替换 ErrorWidget,在 Widget 构建失败时显示自定义错误页面:

scss 复制代码
dart
复制编辑
void main() {
  ErrorWidget.builder = (FlutterErrorDetails details) {
    return Center(child: Text("发生错误: ${details.exceptionAsString()}"));
  };

  runApp(MyApp());
}

5. 总结

机制 作用 适用场景
try-catch 捕获同步异常 同步代码异常
catchError() 处理 Future 异常 异步异常
handleError() 处理 Stream 异常 Stream 发生错误
FlutterError.onError 捕获 Flutter 框架错误 Widget build() 失败
PlatformDispatcher.instance.onError 监听 Engine 级错误 Flutter Engine 发生崩溃
runZonedGuarded 保护全局异步代码 防止 Future 未捕获异常导致崩溃
ErrorWidget.builder 自定义 UI 错误页面 Widget 级别错误

6. 最佳实践

  1. 对所有 Future 代码使用 catchError()
  2. 对所有 Stream 监听使用 handleError()
  3. 使用 FlutterError.onError 统一收集 UI 相关异常
  4. 使用 runZonedGuarded 防止未捕获的异步异常
  5. 上报错误到日志服务(Sentry、Firebase Crashlytics)
  6. 自定义 ErrorWidget.builder 让 UI 崩溃可视化
  7. PlatformDispatcher.instance.onError 监听 Native 层错误

Flutter 的异常处理涉及多个层面,从 Dart 语言层、Flutter 框架层到 UI 组件层,掌握这些机制能有效提升 App 的稳定性,减少崩溃情况。

相关推荐
louisgeek7 小时前
Flutter StatelessWidget 和 StatefulWidget 的区别
flutter
JarvanMo7 小时前
Flutter插件中引用aar
flutter
孤鸿玉11 小时前
[Flutter小试牛刀] 写一个低配版的signals
flutter
科昂15 小时前
Dart 单线程异步模型:从原理到工程实践的系统化解析
android·flutter·dart
fundroid16 小时前
2025 跨平台技术如何选:KMP 与 Flutter 的核心差异
flutter·kotlin·kmp
耳東陈19 小时前
Flutter开箱即用一站式解决方案-新增企业级日志
flutter
顾林海19 小时前
Flutter 图片组件全面解析:从基础加载到高级应用
android·前端·flutter
眼镜会飞19 小时前
Flutter window和Mac中webview2使用Cef替代
windows·flutter·mac
淡写成灰19 小时前
Flutter自定义带有Badger组件组
flutter