Menu
CoddyTech

Una lista de objetos en un modelo

Parte de la sección Gestión del estado del Journey de Flutter de Coddy. Lección 14 de 27.

Un modelo suele contener una lista de objetos, y los propios objetos cambian: se marca una tarea. La regla sigue siendo la misma: el cambio se realiza mediante un método del modelo, y el método llama a 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();
  }
}

Cambiar task.done desde el widget también cambiaría el objeto, pero ningún listener se enteraría, así que la casilla no se movería. El modelo es el único lugar que cambia sus datos y el único lugar que lo comunica.

Fíjate en with. extends indica lo que es una clase, y una clase solo puede extender otra clase. with mezcla capacidades adicionales en una clase, y puedes añadir varias. ChangeNotifier funciona de ambas maneras, así que class TaskList with ChangeNotifier equivale a extends ChangeNotifier y deja extends libre para otra cosa.

challenge icon

Desafío

Intermedio

Al tocar una tarea, task.done cambia directamente en el widget, así que nada en la pantalla se mueve. Traslada el cambio al modelo:

  • Añade un método toggle(Task task) a TaskList que cambie el valor de done de la tarea y notifique a los oyentes.
  • Haz que onChanged del mosaico lo llame.

Pruébalo tú mismo

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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Gestión del estado

Practica por tu cuenta: Compilador de Flutter online