Menu
CoddyTech

Trạng thái lỗi của FutureBuilder

Thuộc phần Dữ liệu và mạng trong hành trình Flutter của Coddy. Bài học 13 trên 27.

FutureBuilder giúp bạn bắt lỗi. Khi future của nó ném ngoại lệ, ứng dụng không bị sập: builder chạy lại với snapshot.hasError được đặt thành true, còn snapshot.error chứa nội dung ngoại lệ.

Nhờ đó, mỗi màn hình tải có ba trạng thái, và builder xử lý từng trạng thái:

if (snapshot.hasError) {
  return Text('Could not load: ${snapshot.error}');
}
if (snapshot.hasData) {
  return Text(snapshot.data!);
}
return const CircularProgressIndicator();

Lỗi, có dữ liệu và vẫn đang tải. Builder chỉ biết xử lý dữ liệu sẽ hiển thị vòng xoay mãi mãi khi lời gọi thất bại, vì sẽ không có dữ liệu nào.

Đặt mỗi bước kiểm tra trước câu lệnh return có thể khiến bước đó không được thực hiện. Nếu câu lệnh return hiển thị vòng xoay khi “không có dữ liệu” nằm trước, dòng xử lý lỗi bên dưới sẽ không bao giờ chạy.

Để xem lỗi trong bản xem trước, hãy viết offline = true; ở dòng đầu tiên của main, rồi nhấn Chạy. offline đến từ api.dart: nó khiến mọi lời gọi thất bại như thể điện thoại không có sóng. Xóa dòng đó trước khi nhấn Kiểm tra.

challenge icon

Thử thách

Trung bình

Khi không có kết nối, màn hình này cứ tải mãi. Hãy thêm trạng thái lỗi cho trình dựng: khi snapshot.hasError, hiển thị Could not load: theo sau là snapshot.error, với cỡ chữ 20.

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> {
  late Future<String> _message;

  @override
  void initState() {
    super.initState();
    _message = fetch('/message');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FutureBuilder<String>(
          future: _message,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return Text(snapshot.data!, style: const TextStyle(fontSize: 24));
            }
            return const CircularProgressIndicator();
          },
        ),
      ),
    );
  }
}
quiz iconTự kiểm tra

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

Tự luyện tập: Trình biên dịch Flutter online