Menu
CoddyTech

Список объектов в модели

Часть раздела Управление состоянием путешествия по 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 свободным для чего-нибудь другого.

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