Список объектов в модели
Часть раздела Управление состоянием путешествия по Flutter на Coddy. Урок 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