Danh sách đối tượng trong 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 14 trên 27.
Một model thường lưu danh sách các đối tượng, và chính các đối tượng cũng thay đổi: một nhiệm vụ được đánh dấu hoàn thành. Quy tắc vẫn vậy: thay đổi diễn ra thông qua một phương thức của model, và phương thức đó gọi notifyListeners():
class TaskList with ChangeNotifier {
final List<Task> _tasks = [Task('Buy milk'), Task('Call Sam')];
List<Task> get tasks => _tasks;
void toggle(Task task) {
task.done = !task.done;
notifyListeners();
}
}Thay đổi task.done từ widget cũng sẽ thay đổi đối tượng, nhưng không listener nào nhận ra điều đó, nên ô sẽ không di chuyển. Model là nơi duy nhất thay đổi dữ liệu của nó, đồng thời cũng là nơi duy nhất thông báo về thay đổi đó.
Lưu ý từ khóa with. extends cho biết một lớp là gì, và một lớp chỉ kế thừa một lớp khác. with thêm các khả năng bổ sung vào một lớp, và bạn có thể thêm nhiều khả năng. ChangeNotifier hoạt động theo cả hai cách, vì vậy class TaskList with ChangeNotifier tương đương với extends ChangeNotifier, đồng thời để dành extends cho một mục đích khác.
Thử thách
Trung bìnhKhi nhấn vào một tác vụ, task.done thay đổi ngay trong widget, nên không có gì trên màn hình thay đổi. Hãy chuyển phần thay đổi này vào model:
- Thêm phương thức
toggle(Task task)vàoTaskListđể đảo trạng tháidonecủa tác vụ và thông báo cho các listener. - Để
onChangedcủa ô gọi phương thức này.
Tự làm thử
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Task {
Task(this.title);
final String title;
bool done = false;
}
class TaskList with ChangeNotifier {
final List<Task> _tasks = [Task('Buy milk'), Task('Walk the dog'), Task('Call Sam')];
List<Task> get tasks => _tasks;
int get doneCount => _tasks.where((t) => t.done).length;
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => TaskList(),
child: 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) {
final list = context.watch<TaskList>();
return Scaffold(
appBar: AppBar(title: Text('${list.doneCount} of ${list.tasks.length} done')),
body: ListView(
children: [
for (final task in list.tasks)
CheckboxListTile(
title: Text(task.title),
value: task.done,
onChanged: (value) {
task.done = !task.done;
},
),
],
),
);
}
}
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
3Provider
Provider: Chia sẻ một mô hìnhGọi notifyListenersProvider: Theo dõi hay đọcProvider: ConsumerHai màn hình, một mô hìnhDanh sách đối tượng trong một mô hìnhNhiều mô hình: MultiProviderTự luyện tập: Trình biên dịch Flutter online