Utilisation de ChangeNotifier dans Flutter
Utilisation de ChangeNotifier dans Flutter
-
Objectif
- Comprendre le concept de ChangeNotifier
- Explorer les approches de consommation de ChangeNotifier
- Illustrer avec des exemples pratiques
- Acquérir des Pratiques pour des Applications de Grande Échelle
-
Présentation
- La gestion d’état est cruciale dans le développement d’applications modernes. Elle permet de synchroniser l’interface utilisateur avec les données sous-jacentes, garantissant que les modifications apportées aux données se reflètent immédiatement dans l’interface. ChangeNotifier est un outil essentiel dans cette gestion, permettant aux widgets d’écouter les changements d’état et de se reconstruire en conséquence.
- Ce tutoriel vise à fournir une compréhension approfondie de l’utilisation de ChangeNotifier dans Flutter, en abordant ses concepts fondamentaux et en présentant des exemples pratiques pour aider les développeurs à intégrer cette fonctionnalité dans leurs projets.
-
Importance de la gestion d’état
- La gestion d’état est cruciale dans le développement d’applications modernes. Elle permet de synchroniser l’interface utilisateur avec les données sous-jacentes, garantissant que les modifications apportées aux données se reflètent immédiatement dans l’interface. ChangeNotifier est un outil essentiel dans cette gestion, permettant aux widgets d’écouter les changements d’état et de se reconstruire en conséquence.
- Ce tutoriel vise à fournir une compréhension approfondie de l’utilisation de ChangeNotifier dans Flutter, en abordant ses concepts fondamentaux et en présentant des exemples pratiques pour aider les développeurs à intégrer cette fonctionnalité dans leurs projets.
-
Utilisation directe de
.addListener
- Fonctionnement
- Étape 1 : Créez une classe qui étend ChangeNotifier et gère l’état.
- Pour utiliser ChangeNotifier, vous devez créer une classe qui étend ChangeNotifier. Voici un exemple simple :
- Dans cet exemple, la classe Counter maintient un compteur _count. La méthode
increment()
augmente la valeur du compteur et appellenotifyListeners()
, ce qui informe tous les widgets qui écoutent ce modèle qu’ils doivent se reconstruire. - Étape 2 : Ajoutez un auditeur à l’instance de la classe.
- Pour utiliser ChangeNotifier dans votre application, vous devez envelopper vos widgets avec un ChangeNotifierProvider. Cela fournit une instance de votre ChangeNotifier à l’arborescence des widgets.
- Étape 3 : Appelez
notifyListeners()
dans votre classe pour déclencher les auditeurs. - Exemple : Un compteur simple
- Avantages :
- Simplicité: Méthode directe et sans dépendances externes.
- Contrôle manuel : Vous contrôlez exactement comment et où les auditeurs sont déclenchés.
- Inconvénients :
- Gestion manuelle : Vous devez ajouter et supprimer manuellement les auditeurs, ce qui peut entraîner des fuites de mémoire si les auditeurs ne sont pas correctement nettoyés.
- Difficile à maintenir : Complexe lorsque plusieurs widgets dépendent du même état.
-
Utilisation avec ChangeNotifierProvider, Consumer, et Provider
- La deuxième approche consiste à utiliser le package Provider, qui offre une manière plus déclarative et réactive de gérer l’état avec ChangeNotifier.
- Fonctionnement
- Le package Provider facilite la gestion d’état en :
- Enveloppant l’arbre des widgets avec un ChangeNotifierProvider pour fournir l’état.
- Utilisant un widget Consumer ou la méthode Provider.of pour accéder à l’état et écouter les changements.
-
Étape 1 : Créez une classe avec ChangeNotifier
-
Étape 2 : Fournir l’état avec ChangeNotifierProvider
- Le ChangeNotifierProvider enveloppe votre application ou une partie de votre arbre de widgets pour fournir l’état à ses descendants.
-
Étape 3 : Consommer l’état avec Consumer ou Provider.of
- Avec
Consumer
: Recommandé pour un usage local et granulaire. - Avec
Provider.of
: Utile pour des cas d’utilisation simples. -
Comparaison entre
Consumer
etProvider.of
- Avantages :
- Réactif et Automatique : Les widgets se reconstruisent automatiquement lorsque l’état change.
- Lisibilité : Favorise une séparation claire entre l’état et l’interface utilisateur.
- Efficace : Consumer permet de reconstruire uniquement les widgets nécessaires.
- Inconvénients :
- Complexité initiale : Peut être intimidant pour les débutants.
- Dépendance externe : Nécessite d’ajouter le package Provider.
- Résumé Comparatif
Le ChangeNotifier
peut être utilisé directement grâce à la méthode .addListener
, car il est un sous-type de Listenable. Cela permet d’ajouter des auditeurs (callbacks) pour réagir aux modifications de l’état.
class Counter extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // Notifie les auditeurs du changement
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Counter(),
child: MyApp(),
),
);
}
import 'package:flutter/material.dart';
class Counter extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // Notifie tous les auditeurs.
}
}
void main() {
final counter = Counter();
counter.addListener(() {
print('Le compteur a changé : ${counter.count}');
});
counter.increment(); // Affiche : "Le compteur a changé : 1".
counter.increment(); // Affiche : "Le compteur a changé : 2".
}
class Counter extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // Notifie tous les widgets consommateurs.
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Counter(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CounterScreen(),
);
}
}
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
// Modèle ChangeNotifier pour gérer l'état du compteur
class Counter extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // Notifie les widgets écoutant ce modèle
}
}
// Écran principal utilisant le modèle Counter
class CounterScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Compteur')),
body: Center(
child: Consumer( // Consomme le modèle Counter
builder: (context, counter, child) {
return Text(
'Compteur : ${counter.count}',
style: TextStyle(fontSize: 24),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => context.read().increment(), // Incrémente le compteur
child: Icon(Icons.add),
),
);
}
}
void main() {
runApp(
ChangeNotifierProvider( // Fournit le modèle Counter à l'application
create: (context) => Counter(),
child: MaterialApp(
home: CounterScreen(),
),
),
);
}
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
// Modèle ChangeNotifier pour gérer l'état du compteur
class Counter extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // Notifie les widgets écoutant ce modèle
}
}
// Écran principal utilisant le modèle Counter
class CounterScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counter = Provider.of(context); // Récupère le modèle Counter
return Scaffold(
appBar: AppBar(title: Text('Compteur')),
body: Center(
child: Text(
'Compteur : ${counter.count}', // Affiche la valeur actuelle du compteur
style: TextStyle(fontSize: 24),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => counter.increment(), // Incrémente le compteur lorsqu'on appuie sur le bouton
child: Icon(Icons.add),
),
);
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Counter(), // Crée une instance de Counter
child: MaterialApp(
home: CounterScreen(), // Définit l'écran principal
),
),
);
}
Aspect Consumer Provider.of
Performance Optimisé : reconstruit uniquement le widget cible. Moins optimisé : reconstruit tout le widget parent.
Lisibilité Plus clair pour les grands arbres de widgets. Plus compact mais moins lisible.
Usage recommandé Lorsque vous voulez limiter la reconstruction. Pour des usages rapides ou ponctuels.
Critère | Avec .addListener |
Avec Provider |
---|---|---|
Complexité | Simple pour des cas isolés. | Meilleur pour des projets de grande envergure. |
Maintenance | Moins maintenable dans des scénarios complexes. | Plus maintenable grâce à une gestion d’état centralisée. |
Gestion des auditeurs | Manuelle (risque de fuites mémoire). | Automatique grâce à ChangeNotifierProvider . |
Performances | Direct et léger. | Optimisé pour des applications plus grandes. |
Exemple d’usage | Projets simples ou expérimentations. | Applications professionnelles ou complexes. |