Menu
CoddyTech

Ném lỗi

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

Lỗi không chỉ xảy ra với máy chủ. Các hàm của bạn cũng có thể từ chối tiếp tục. Khi hàm nhận được thứ mà nó không thể xử lý, nó sẽ ném ra:

Future<void> saveName(String name) async {
  if (name.isEmpty) {
    throw Exception('The name cannot be empty');
  }
  // lưu tên
}

throw dừng hàm ngay tại đó, giống như return, nhưng trả về một lỗi thay vì một giá trị. Exception('...') là lỗi, kèm theo thông báo cho biết điều gì đã xảy ra.

Phần code gọi hàm sẽ bắt lỗi bằng try và catch, giống hệt như lỗi từ fetch. Khi chuyển thành văn bản, một Exception bắt đầu bằng Exception: , sau đó là thông báo của bạn.

Một fetch thực tế cũng hoạt động như vậy. Mọi phản hồi từ máy chủ đều có mã trạng thái: 200 nghĩa là thành công, 404 nghĩa là không tìm thấy. Khi mã trạng thái không phải 200, code của bạn sẽ ném ra lỗi, để màn hình không hiển thị một phản hồi lỗi như thể đó là dữ liệu:

final response = await http.get(Uri.parse(url));
if (response.statusCode != 200) {
  throw Exception('The server answered ${response.statusCode}');
}
return response.body;
challenge icon

Thử thách

Dễ

Nhấn Save khi trường còn trống: màn hình hiển thị Saved: mà không có tên. Sửa saveName để hàm này từ chối tên trống: sau khi chờ, nếu name trống, hãy ném ra Exception('The name cannot be empty'). Hàm save đã bắt ngoại lệ và hiển thị thông báo.

Tự làm thử

import 'package:flutter/material.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: NameScreen(),
    );
  }
}

class NameScreen extends StatefulWidget {
  const NameScreen({super.key});

  @override
  State<NameScreen> createState() => _NameScreenState();
}

class _NameScreenState extends State<NameScreen> {
  final controller = TextEditingController();
  String status = '';

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  Future<void> saveName(String name) async {
    await Future.delayed(const Duration(seconds: 1));
  }

  Future<void> save() async {
    try {
      await saveName(controller.text);
      setState(() {
        status = 'Saved: ${controller.text}';
      });
    } catch (e) {
      setState(() {
        status = '$e';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextField(
              controller: controller,
              decoration: const InputDecoration(labelText: 'Name'),
            ),
            const SizedBox(height: 16),
            ElevatedButton(onPressed: save, child: const Text('Save')),
            const SizedBox(height: 16),
            Text(status, style: const TextStyle(fontSize: 18)),
          ],
        ),
      ),
    );
  }
}
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