Menu
CoddyTech

Varios modelos: MultiProvider

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

Mantén cada modelo centrado en una sola cosa: la puntuación en una clase, las vidas en otra. Los modelos pequeños son fáciles de leer, y un widget solo observa lo que necesita. Una aplicación con varios modelos necesita varios proveedores.

Podrías anidarlos, con un proveedor como hijo del siguiente, pero el código se desplaza hacia la derecha con cada modelo. MultiProvider acepta una lista plana:

runApp(
  MultiProvider(
    providers: [
      ChangeNotifierProvider(create: (context) => Score()),
      ChangeNotifierProvider(create: (context) => Lives()),
    ],
    child: const MyApp(),
  ),
);

Los proveedores de la lista no tienen un child propio: MultiProvider los apila por ti y coloca child debajo de todos ellos. Todos los widgets descendientes pueden observar o leer cualquiera de los modelos, cada uno por su tipo: context.watch<Lives>().

challenge icon

Desafío

Fácil

La página del juego observa dos modelos, Score y Lives, pero main solo proporciona la puntuación, por lo que la aplicación muestra un error.

  • Reemplaza el proveedor en main por un MultiProvider que proporcione ambos modelos.

Pruébalo tú mismo

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class Score extends ChangeNotifier {
  int _points = 0;

  int get points => _points;

  void hit() {
    _points += 10;
    notifyListeners();
  }
}

class Lives extends ChangeNotifier {
  int _left = 3;

  int get left => _left;

  void miss() {
    if (_left > 0) {
      _left--;
      notifyListeners();
    }
  }
}

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => Score(),
      child: const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: GamePage(),
    );
  }
}

class GamePage extends StatelessWidget {
  const GamePage({super.key});

  @override
  Widget build(BuildContext context) {
    final points = context.watch<Score>().points;
    final lives = context.watch<Lives>().left;
    return Scaffold(
      appBar: AppBar(title: Text('Lives: $lives')),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('Points: $points', style: const TextStyle(fontSize: 40)),
            const SizedBox(height: 16),
            Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                ElevatedButton(
                  onPressed: () => context.read<Score>().hit(),
                  child: const Text('Hit'),
                ),
                const SizedBox(width: 16),
                ElevatedButton(
                  onPressed: () => context.read<Lives>().miss(),
                  child: const Text('Miss'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
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