Menu
CoddyTech

Provider: Chia sẻ một mô hình

Thuộc phần Quản lý trạng thái trong hành trình Flutter của Coddy. Bài học 9 trên 27.

Đưa state lên cao hơn rất hiệu quả khi các widget ở gần nhau. Khi cần dùng một giá trị ở khắp ứng dụng, trên hai màn hình, trong thanh trên cùng và sâu bên trong một danh sách, bạn sẽ phải truyền giá trị đó qua từng widget ở giữa. Provider giúp bạn không phải làm vậy. Đây là một package: một tập hợp code mà bạn import bằng import 'package:provider/provider.dart';.

Package này có ba phần. Đầu tiên là một model: một lớp lưu dữ liệu và extends ChangeNotifier. Các phương thức của lớp này thay đổi dữ liệu rồi gọi notifyListeners():

class CupCounter extends ChangeNotifier {
  int _cups = 0;
  int get cups => _cups;

  void addCup() {
    _cups++;
    notifyListeners();
  }
}

Thứ hai, một ChangeNotifierProvider ở vị trí cao trong cây widget tạo model một lần rồi truyền model đó cho mọi widget bên dưới:

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => CupCounter(),
      child: const MyApp(),
    ),
  );
}

Thứ ba, bất kỳ widget nào bên dưới cũng có thể lấy model: dùng context.watch<CupCounter>() để hiển thị model, dùng context.read<CupCounter>() để gọi một phương thức. Tiêu đề và nút bên dưới dùng cùng một bộ đếm, nhưng không widget nào cần nhận dữ liệu được truyền vào.

challenge icon

Thử thách

Trung bình

Mở ứng dụng: ứng dụng báo lỗi vì tiêu đề yêu cầu một CupCounter, nhưng không có thành phần nào phía trên cung cấp đối tượng này.

  • Trong main, bọc MyApp trong một ChangeNotifierProvider tạo một CupCounter.

Tự làm thử

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class CupCounter extends ChangeNotifier {
  int _cups = 0;

  int get cups => _cups;

  void addCup() {
    _cups++;
    notifyListeners();
  }
}

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const CupsTitle()),
      body: const Center(child: AddCupButton()),
    );
  }
}

class CupsTitle extends StatelessWidget {
  const CupsTitle({super.key});

  @override
  Widget build(BuildContext context) {
    final counter = context.watch<CupCounter>();
    return Text('Cups: ${counter.cups}');
  }
}

class AddCupButton extends StatelessWidget {
  const AddCupButton({super.key});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        context.read<CupCounter>().addCup();
      },
      child: const Text('Another cup'),
    );
  }
}
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 Quản lý trạng thái

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