Menu
CoddyTech

Model内のオブジェクトのリスト

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 はクラスが何であるかを示し、クラスが継承できるクラスは1つだけです。with はクラスに追加の機能を組み込み、複数追加することもできます。ChangeNotifier はどちらの方法でも使えるため、class TaskList with ChangeNotifier は extends ChangeNotifier と同じであり、別のものに使うために extends を空けておけます。

challenge icon

チャレンジ

中級

タスクをタップすると、ウィジェット内でtask.doneが切り替わるため、画面上の何も動きません。変更処理をモデルに移しましょう。

  • TaskListに、タスクのdoneを切り替えてリスナーに通知するメソッドtoggle(Task task)を追加します。
  • タイルの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オンラインコンパイラ