רשימת אובייקטים במודל
חלק מהיחידה ניהול מצב במסלול ה-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 אונליין