Menu
CoddyTech

Provider : partager un modèle

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

La remontée de l’état fonctionne tant que les widgets sont proches. Lorsqu’une valeur est nécessaire dans toute l’application, sur deux écrans, dans la barre supérieure ou au plus profond d’une liste, il faudrait la transmettre à chaque widget intermédiaire. Provider évite cela. C’est un paquet : un ensemble de code que vous importez avec import 'package:provider/provider.dart';.

Il comporte trois parties. D’abord, un modèle : une classe qui contient les données et extends ChangeNotifier. Ses méthodes modifient les données, puis appellent notifyListeners() :

class CupCounter extends ChangeNotifier {
  int _cups = 0;
  int get cups => _cups;

  void addCup() {
    _cups++;
    notifyListeners();
  }
}

Ensuite, un ChangeNotifierProvider placé haut dans l’arborescence crée le modèle une seule fois et le transmet à chaque widget situé en dessous :

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

Enfin, chaque widget situé en dessous le demande : context.watch<CupCounter>() pour l’afficher, context.read<CupCounter>() pour appeler une méthode. Le titre et le bouton ci-dessous obtiennent le même compteur, et rien n’est transmis à l’un ou à l’autre.

challenge icon

Défi

Moyen

Ouvre l’application : une erreur s’affiche, car le titre demande un CupCounter et qu’aucun élément au-dessus ne lui en fournit un.

  • Dans main, enveloppe MyApp dans un ChangeNotifierProvider qui crée un CupCounter.

Essayez vous-même

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

class CupCounter extends ChangeNotifier {
  int _cups = 0;

  int get cups => _cups;

  void addCup() {
    _cups++;
    notifyListeners();
  }
}

void main() {
  runApp(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) {
    return Scaffold(
      appBar: AppBar(title: const CupsTitle()),
      body: const Center(child: AddCupButton()),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final counter = context.watch<CupCounter>();
    return Text('Cups: ${counter.cups}');
  }
}

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

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        context.read<CupCounter>().addCup();
      },
      child: const Text('Another cup'),
    );
  }
}
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