一、Dart语言错误处理的基本概念
在Dart开发中,错误处理是保证程序健壮性的关键。无论是Flutter应用还是后端服务,未处理的异常都可能导致应用崩溃或数据丢失。Dart中的错误主要分为两类:Exception(可预见的异常)和Error(通常表示程序逻辑错误)。
// 示例1:Dart中的Exception和Error
void main() {
try {
// 人为抛出一个Exception
throw Exception('这是一个自定义异常');
} catch (e) {
print('捕获到异常: $e'); // 输出:捕获到异常: Exception: 这是一个自定义异常
}
try {
// 人为抛出一个Error
throw ArgumentError('无效参数');
} catch (e) {
print('捕获到错误: $e'); // 输出:捕获到错误: Invalid argument: 无效参数
}
}
关键点:
Exception通常用于可恢复的错误(如网络请求失败)。Error表示严重问题(如空指针),通常不需要捕获。
二、try-catch-finally的实战用法
Dart使用try-catch-finally处理异常,语法与其他语言类似,但支持更灵活的捕获方式:
// 示例2:捕获特定类型的异常
void fetchData() {
try {
var data = {'name': 'Dart'};
print(data['age']!); // 触发空指针异常(NoSuchMethodError)
} on NoSuchMethodError {
print('字段不存在!'); // 精准捕获特定错误
} catch (e, s) {
print('其他异常: $e');
print('堆栈信息: $s'); // 打印调用栈
} finally {
print('清理资源'); // 无论是否异常都会执行
}
}
注意事项:
- 使用
on关键字可针对异常类型分别处理。 catch (e, s)中的s是堆栈跟踪(Stack Trace),便于调试。
三、异步代码的错误处理
Dart的异步操作(如Future和Stream)需要通过特殊方式处理错误:
// 示例3:Future的错误处理
Future<void> loadUserData() async {
try {
var data = await Future.error('模拟网络错误');
print(data);
} catch (e) {
print('异步错误: $e'); // 输出:异步错误: 模拟网络错误
}
}
// 示例4:Stream的错误监听
Stream<int> countNumbers() async* {
for (int i = 1; i <= 3; i++) {
if (i == 2) throw '出错啦!';
yield i;
}
}
void main() {
countNumbers().listen(
(data) => print('数据: $data'),
onError: (e) => print('Stream错误: $e'), // 输出:Stream错误: 出错啦!
cancelOnError: false, // 错误后是否继续监听
);
}
关联技术:
async/await简化了异步代码的编写,但错误处理仍需try-catch。Stream的错误可通过listen的onError回调处理。
四、自定义异常与最佳实践
通过继承Exception类实现自定义异常:
// 示例5:自定义业务异常
class AuthException implements Exception {
final String message;
AuthException(this.message);
@override
String toString() => 'AuthException: $message';
}
void login(String password) {
if (password.isEmpty) {
throw AuthException('密码不能为空');
}
}
void main() {
try {
login('');
} on AuthException catch (e) {
print(e); // 输出:AuthException: 密码不能为空
}
}
最佳实践:
- 早抛出,晚捕获:在底层抛出异常,在高层统一处理。
- 避免捕获所有错误:只处理能恢复的异常,
Error通常不应捕获。 - 日志记录:结合
logger包记录异常上下文。
五、应用场景与技术优缺点
典型场景:
- API请求失败(如超时、404)。
- 用户输入验证(如格式错误)。
- 文件读写权限问题。
优缺点分析:
| 优点 | 缺点 |
|------|------|
| 语法简洁,与Java/JavaScript类似 | 异步错误处理稍显复杂 |
| 支持异常类型细分 | 部分框架(如Flutter)需要额外处理Zone错误 |
总结:
Dart的错误处理机制既灵活又强大,合理使用能显著提升代码可靠性。在Flutter开发中,还需注意Widget树的错误边界(通过ErrorWidget处理),但那是另一个话题了。
评论