Menu
CoddyTech

Plusieurs modèles : MultiProvider

Fait partie de la section Gestion d’état du Journey Flutter de Coddy. Leçon 15 sur 27.

Consacre chaque modèle à une seule chose : le score dans une classe, les vies dans une autre. Les petits modèles sont faciles à lire, et un widget ne surveille que ce dont il a besoin. Une application avec plusieurs modèles nécessite plusieurs fournisseurs.

Tu pourrais les imbriquer, un fournisseur étant l’enfant du suivant, mais le code se décale vers la droite à chaque modèle. MultiProvider prend plutôt une liste à plat :

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

Les fournisseurs de la liste n’ont pas leur propre child : MultiProvider les empile pour toi et place child sous eux tous. Chaque widget en aval peut surveiller ou lire n’importe lequel des modèles, chacun par son type : context.watch<Lives>().

challenge icon

Défi

Facile

La page du jeu observe deux modèles, Score et Lives, mais main ne fournit que le score, ce qui provoque une erreur dans l’application.

  • Remplace le fournisseur dans main par un MultiProvider qui fournit les deux modèles.

Essayez vous-même

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 iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Gestion d’état

Entraînez-vous par vous-même : Compilateur Flutter en ligne