Menu
CoddyTech

模型中的对象列表

本课属于 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 留给其他用途。

challenge icon

挑战

中等

点击任务会直接在组件中切换 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;
              },
            ),
        ],
      ),
    );
  }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

状态管理中的所有课

自己练习: Flutter 在线编译器