Menu
CoddyTech
flag Ar iconالعربيةdown icon

قائمة من الكائنات في نموذج

جزء من قسم إدارة الحالة في رحلة 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 عبر الإنترنت