1つのタスク(Todo)を表すクラスを定義します。
イミュータブルにすることで、状態を安全に管理できます。
class Todo {
final String id; //TodoのID
final String title; //Todoのタイトル
final bool isCompleted; //完了状態
// (1)
Todo({ //コンストラクタ
required this.id, //インスタンス作成時にrequiredが必要
required this.title,
required this.isCompleted,
});
// (2)
Todo copyWith({
String? title,
bool? isCompleted,
}) {
return Todo(
id: id, //IDは常に同じ
title: title ?? this.title, //新しい値か既存の値
isCompleted: isCompleted ?? this.isCompleted,
);
}
}
(1) 使用例
final todo = Todo(
id: '1',
title: '買い物に行く',
isCompleted: false,
);
(2) 使用例
final todo = Todo(id: '1', title: '掃除', isCompleted: false);
// タイトルだけ変更
final updated1 = todo.copyWith(title: '大掃除');
// 完了状態だけ変更
final updated2 = todo.copyWith(isCompleted: true);
// 両方変更
final updated3 = todo.copyWith(
title: '洗濯',
isCompleted: true,
);
idは変更不可(常に元の値を使用)??演算子:新しい値がnullなら既存の値を使うclass TodoNotifier extends Notifier<List<Todo>> {. //<List,Todo>>型の状態を管理
@override
List<Todo> build() {. //アプリ起動時やProviderが初めて読み込まれた時に呼ばれる
return []; // 初期状態は空のリスト
}
// (1)
void add(String title) {
state = [
...state, //スプレッド演算子
Todo(
id: DateTime.now().toString(), //現在時刻をIDに使用
title: title,
isCompleted: false,
),
];
}
// (2)
void toggle(String id) {. //完了状態の切り替え
state = state
.map((todo) => todo.id == id
? todo.copyWith(isCompleted: !todo.isCompleted)//対象のtodoは反転
: todo) //それ以外はそのまま
.toList();
}
// (3)
void remove(String id) { //Todo削除
state = state.where((todo) => todo.id != id).toList();
}
}
(1) 動作の流れ:
...stateで既存のTodo全てをコピー