Flutter Provider
Flutter Provider
-
Objectif
- Simplifier la gestion d’état dans une application Flutter.
- Partager des données entre widgets sans avoir besoin de passer des paramètres manuellement (lifting state up).
- Assurer une interface réactive, toujours synchronisée avec les données.
- Proposer une approche claire, simple et évolutive par rapport à
setState()
. -
Présentation
- Flutter Provider est une solution de gestion d’état pour les applications Flutter. Elle permet de gérer facilement l’état de l’application et de le partager entre plusieurs widgets, facilitant ainsi l’accès aux données là où elles sont nécessaires.
- Vous stockez les données dans un emplacement central appelé
provider
et y accédez depuis n’importe quel widget de votre application. - Dès que les données changent, le
provider
les met à jour, garantissant la cohérence et la réactivité de l’UI. - Les principaux avantages :
- Centralisation de l’état
- Découplage des widgets
- Optimisation des performances (rebuild ciblé)
-
Les types de Provider les plus courants
-
Provider (de base)
- Fournit un objet simple (ex: une classe de service ou un objet).
- Ne notifie pas automatiquement les changements (objet immuable ou service stateless).
- Exemple :
-
ChangeNotifierProvider <T>
- Utilisé pour des données modifiables avec notification des changements.
- Repose sur la classe
ChangeNotifier
. - Cas typique : un panier d’achat, compteur, todo-list.
-
StreamProvider <T>
- Expose un
Stream
(Firebase, WebSocket, etc.). -
FutureProvider <T>
- Expose un
Future
pour des données asynchrones (ex: appel HTTP). -
MultiProvider
- Permet de regrouper plusieurs providers dans un seul point d’entrée.
-
NotifierProvider <T extends Notifier>
- Introduit en Provider 2.x pour simplifier la gestion d’état immutable et réactif.
- Plus moderne que
ChangeNotifierProvider
, inspiré de Riverpod. - Avantage : n’utilise pas
notifyListeners()
, mais renvoie un nouvel état. -
AsyncNotifierProvider <T>
- Variante de
NotifierProvider
pour gérer des données asynchrones (Future/Stream). - Pratique pour les appels API, Firebase, etc.
-
Comment utiliser un package
provider
Flutter ? - Étape 1 : ajouter la dépendance dans
pubspec.yaml
. - Étape 2 : créer un modèle de données.
- Étape 3 : envelopper l’application dans un Provider.
- Étape 4 : consommer les données avec
context.watch
,Consumer
ouSelector
. -
Utilisation directe de
.addListener
- Vous pouvez écouter directement les changements d’un
ChangeNotifier
. - Moins utilisé, mais utile pour du code métier hors widgets.
-
Comparaison des principaux Providers
-
Bonnes pratiques
- Préférer
context.read
pour déclencher une action, etcontext.watch
pour reconstruire l’UI. - Découper les providers pour garder des responsabilités claires.
- Utiliser
Selector
pour éviter des rebuilds inutiles. - Pour les projets modernes, envisager
NotifierProvider
/AsyncNotifierProvider
.

// Création
Provider<String>(
create: (context) => "Alice Dupont",
child: MonWidget(),
);
// Utilisation
Text(Provider.of<String>(context)); // Affiche "Alice Dupont"
class Counter with ChangeNotifier {
int value = 0;
void increment() {
value++;
notifyListeners();
}
}
ChangeNotifierProvider(
create: (_) => Counter(),
child: MyApp(),
);
Utilisation avec Consumer :
Consumer<Counter>(
builder: (context, counter, child) {
return Text('${counter.value}');
},
);
StreamProvider<int>(
create: (_) => Stream.periodic(Duration(seconds: 1), (i) => i),
initialData: 0,
child: MyApp(),
);
FutureProvider<User>(
create: (_) async => fetchUser(),
initialData: User.empty(),
child: MyApp(),
);
MultiProvider(
providers: [
Provider(create: (_) => MyService()),
ChangeNotifierProvider(create: (_) => Counter()),
StreamProvider(create: (_) => myStream(), initialData: 0),
],
child: MyApp(),
);
class Counter extends Notifier<int> {
@override
int build() => 0;
void increment() => state++;
}
final counterProvider = NotifierProvider<Counter, int>(() => Counter());
Utilisation :
final count = context.watch(counterProvider);
class UserNotifier extends AsyncNotifier<User> {
@override
Future<User> build() async {
return await fetchUser();
}
}
final userProvider = AsyncNotifierProvider<UserNotifier, User>(() => UserNotifier());
Utilisation :
final user = context.watch(userProvider);
if (user is AsyncLoading) {
return CircularProgressIndicator();
} else if (user is AsyncError) {
return Text('Erreur');
} else {
return Text(user.value.name);
}
final counter = Counter();
counter.addListener(() {
print("Nouveau compteur: ${counter.value}");
});
Provider | Type d’état | Méthode de mise à jour | Cas d’utilisation | Exemple simplifié |
---|---|---|---|---|
ChangeNotifierProvider | Mutable (objet modifié) | notifyListeners() |
Compteur, panier, todo-list (UI dépendante de modifications fréquentes) |
|
NotifierProvider | Immuable (nouvel état produit) | Réaffectation de state |
Gestion moderne d’états synchrones (+ simple et performant) |
|
AsyncNotifierProvider | Asynchrone (Future / Stream) | Résultat d’une tâche asynchrone | Appels API, Firebase, BDD distante |
|