Blog
Riverpod s'est imposé comme la référence pour la gestion d'état en Flutter. Voici les patterns concrets que j'utilise en production.

La gestion d'état est l'un des sujets les plus débattus dans l'écosystème Flutter. setState, Provider, Bloc, GetX, MobX... les options ne manquent pas. Depuis deux ans, j'utilise Riverpod sur la quasi-totalité de mes projets Flutter, et ce choix tient très bien à l'usage.
Riverpod n'est pas juste un gestionnaire d'état : c'est un système complet d'injection de dépendances, de gestion des états asynchrones, et de recomposition optimisée. Voici les patterns qui me servent le plus en production.
Provider est le prédécesseur direct de Riverpod (même auteur, Remi Rousselet). Riverpod corrige ses limitations principales : pas de dépendance au BuildContext pour accéder aux providers, typage plus fort, support natif de l'async et gestion des erreurs intégrée.
Bloc est une bonne option pour les équipes qui aiment les patterns événement/état explicites. Le coût d'entrée est plus élevé et le code plus verbeux, mais la traçabilité est excellente sur des apps avec des flux d'état très complexes.
Riverpod occupe un entre-deux confortable : moins rigide que Bloc, plus structuré et testable que setState ou GetX. La courbe d'apprentissage est raisonnable et le gain en maintenabilité est immédiat.
Riverpod propose plusieurs types de providers. Les deux que j'utilise le plus sont NotifierProvider et AsyncNotifierProvider.
NotifierProvider s'utilise pour un état synchrone avec logique : par exemple un panier d'achats, des filtres actifs, ou des préférences utilisateur. La classe Notifier expose une méthode build() qui retourne l'état initial, et des méthodes publiques pour modifier l'état.
AsyncNotifierProvider est son équivalent pour les états asynchrones : chargement de données depuis une API, stream Firestore, opération avec await. Le state est de type AsyncValue, ce qui force à gérer explicitement les cas loading, data et error dans l'UI une très bonne pratique.
Provider simple (sans Notifier) reste utile pour les valeurs dérivées ou les dépendances injectées : instance de repository, valeur calculée depuis un autre provider.
Le pattern que j'adopte systématiquement en production combine Riverpod avec une Clean Architecture allégée.
Au niveau le plus bas : un repositoryProvider qui expose une instance du repository (classe abstraite + implémentation concrète). Ce provider peut être overridé dans les tests avec un mock.
Au-dessus : un ou plusieurs AsyncNotifierProviders qui consomment le repository et exposent les données transformées à l'UI. Ces providers ne contiennent pas de logique métier ils orchestrent les appels.
Dans les widgets : ConsumerWidget qui watch les providers dont il dépend. La recomposition est automatique et granulaire seul le widget qui écoute un provider est reconstruit quand ce provider change. Ce découpage rend chaque couche testable indépendamment et évite les anti-patterns classiques.
Un avantage souvent sous-estimé de Riverpod : la gestion d'erreur est first-class. Avec AsyncValue, chaque état asynchrone est soit loading, soit data(value), soit error(error, stackTrace).
Dans l'UI, le pattern idiomatique est d'utiliser when() sur l'AsyncValue pour mapper chaque cas vers un widget différent. Pas de try/catch dispersés dans les widgets, pas de booléens isLoading/hasError à synchroniser manuellement.
Pour les erreurs globales (token expiré, perte de connexion), un provider dédié qui observe les erreurs remontées et les traite centralement permet d'afficher un snackbar, de rediriger vers le login, ou de déclencher un retry automatique depuis un seul endroit.
Pour conclure
Riverpod est aujourd'hui ma solution par défaut pour la gestion d'état en Flutter. Il ne résout pas tous les problèmes aucune solution ne le fait mais il pose des contraintes qui poussent vers un code plus propre, plus testable et plus maintenable. Si vous démarrez un projet Flutter et hésitez sur la gestion d'état, Riverpod est un excellent point de départ.
Discuter d'un projet
Un call de 20 minutes pour cadrer votre besoin et vous proposer un plan d'action concret.