Bắt lỗi bằng try
Thuộc phần Dữ liệu và mạng trong hành trình Flutter của Coddy. Bài học 10 trên 27.
Lệnh gọi mạng có thể thất bại: điện thoại mất sóng, máy chủ ngừng hoạt động, đường dẫn không đúng. Khi fetch thất bại, nó ném ra một lỗi: ApiException, một lớp nhỏ ở đầu api.dart, có statusCode và message. Lỗi không được xử lý sẽ dừng hàm của bạn và xuất hiện dưới dạng lỗi màu đỏ trong Console, còn người dùng sẽ thấy vòng xoay tải mãi không dừng.
Bắt lỗi bằng try và catch:
try {
final text = await fetch('/message');
// chỉ chạy khi fetch thành công
} catch (e) {
// chỉ chạy khi fetch ném ra ngoại lệ
print('It failed: $e');
}Dart chạy khối lệnh try. Nếu có bất cứ thứ gì trong khối lệnh đó ném ra lỗi, Dart chuyển thẳng đến catch, và e giữ lỗi đó. Các dòng sau dòng gây lỗi trong try sẽ không chạy.
Đặt chính await bên trong try: đó là dòng gây ra lỗi. Sau đó giải thích điều đã xảy ra bằng lời để người dùng hiểu, thay vì để ứng dụng gặp sự cố.
Để xem lỗi trong bản xem trước, viết offline = true; ở dòng đầu tiên của main rồi nhấn Chạy. offline nằm trong api.dart: nó khiến mọi lệnh gọi đều thất bại như thể điện thoại mất sóng. Xóa dòng đó trước khi nhấn Kiểm tra.
Thử thách
Trung bìnhHãy để loadMessage xử lý được khi lệnh gọi thất bại:
- đặt
fetchvàsetStatesau đó vào khốitry - trong
catch (e), dừng vòng xoay và đặt thông báo thànhCould not load: $e
Tự làm thử
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')),
],
),
),
);
}
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Dữ liệu và mạng
3Khi lời gọi hàm thất bại
Bắt lỗi bằng tryNém lỗiDọn dẹp với finallyTrạng thái lỗi của FutureBuilderNút thử lạiTự luyện tập: Trình biên dịch Flutter online