模型中的对象列表
本课属于 Coddy Flutter 学习旅程的“状态管理”单元。第 14 课,共 27 课。
模型通常会保存一个对象列表,而对象本身也会发生变化:某个任务被勾选。规则不变:更改要通过模型的方法进行,并由该方法调用 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();
}
}如果从组件中更改 task.done,对象也会发生变化,但没有监听器会收到通知,所以复选框不会移动。模型是唯一负责更改数据的地方,也是唯一负责通知的地方。
注意 with。extends 表示一个类是什么,而一个类只能继承另一个类。with 会为类混入额外的能力,而且你可以添加多个。ChangeNotifier 两种方式都适用,所以 class TaskList with ChangeNotifier 和 extends ChangeNotifier 的作用相同,并且可以把 extends 留给其他用途。
挑战
中等点击任务会直接在组件中切换 task.done,因此屏幕上的内容不会变化。把这个修改移到模型中:
- 在
TaskList中添加一个方法toggle(Task task),用于切换任务的done状态并通知监听器。 - 让此列表项的
onChanged调用它。
亲手试试
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;
},
),
],
),
);
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
状态管理中的所有课
自己练习: Flutter 在线编译器