使用 try 捕获错误
本课属于 Coddy Flutter 学习旅程的“数据与网络”单元。第 10 课,共 27 课。
网络调用可能会失败:手机没有信号、服务器宕机,或者路径错误。fetch 失败时,会抛出一个错误:一个 ApiException,它是在 api.dart 顶部定义的小类,包含 statusCode 和 message。如果没有捕获错误,函数就会停止运行,控制台会显示红色错误,而用户会一直看到转不停的加载图标。
用 try 和 catch 捕获错误:
try {
final text = await fetch('/message');
// 只有 fetch 成功时才会运行
} catch (e) {
// 只有 fetch 抛出异常时才会运行
print('It failed: $e');
}Dart 会运行 try 代码块。如果其中任何内容抛出错误,Dart 会直接跳到 catch,并将错误存入 e。try 中出错行之后的代码都不会运行。
把 await 本身放在 try 里面:抛出错误的就是这一行。然后用文字告诉用户发生了什么,而不是让程序崩溃。
要在预览中查看失败效果,请在 main 的第一行写入 offline = true;,然后按“运行”。offline 来自 api.dart:它会让每次调用都失败,就像手机没有信号一样。按“检查”前,请删除这一行。
挑战
中等让 loadMessage 在调用失败时也能正常处理:
- 把
fetch和它后面的setState放进try代码块中 - 在
catch (e)中,停止加载动画,并将消息设置为Could not load: $e
亲手试试
import 'package:flutter/material.dart';
import 'api.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: MessageScreen(),
);
}
}
class MessageScreen extends StatefulWidget {
const MessageScreen({super.key});
@override
State<MessageScreen> createState() => _MessageScreenState();
}
class _MessageScreenState extends State<MessageScreen> {
String message = 'No message yet';
bool loading = false;
Future<void> loadMessage() async {
setState(() {
loading = true;
});
final text = await fetch('/message');
setState(() {
message = text;
loading = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
loading
? const CircularProgressIndicator()
: Text(message, style: const TextStyle(fontSize: 24)),
const SizedBox(height: 24),
ElevatedButton(onPressed: loadMessage, child: const Text('Load message')),
],
),
),
);
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
数据与网络中的所有课
自己练习: Flutter 在线编译器