Aller au contenu principal
Flutter Dart Mobile

Guide complet du State Management en Flutter

Découvrez les différentes approches de gestion d'état en Flutter : setState, Provider, Riverpod et BLoC. Avec des exemples pratiques pour chaque méthode.

Guide complet du State Management en Flutter

La gestion de l’état est l’un des aspects les plus importants du développement d’applications Flutter. Dans cet article, nous allons explorer les différentes approches disponibles et voir quand utiliser chacune d’elles.

Qu’est-ce que le State Management ?

Le state management (gestion d’état) fait référence à la façon dont vous gérez les données qui peuvent changer au fil du temps dans votre application. Ces données peuvent inclure :

  • Les informations de l’utilisateur connecté
  • Les données récupérées depuis une API
  • L’état de l’interface utilisateur (formulaires, navigation, etc.)
  • Les préférences de l’application

Une bonne gestion de l’état est essentielle pour créer des applications maintenables et performantes.

1. setState - La méthode de base

La méthode setState est la façon la plus simple de gérer l’état local d’un widget. Elle est parfaite pour les cas simples où l’état n’a pas besoin d’être partagé entre plusieurs widgets.

class CounterWidget extends StatefulWidget {
  const CounterWidget({super.key});

  @override
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Compteur: $_counter'),
        ElevatedButton(
          onPressed: _incrementCounter,
          child: const Text('Incrémenter'),
        ),
      ],
    );
  }
}

Avantages de setState

  • Simple à comprendre et à utiliser
  • Pas de dépendances externes
  • Parfait pour l’état local

Inconvénients

  • Ne convient pas pour l’état partagé entre widgets
  • Peut devenir complexe dans les grandes applications

2. Provider - La solution recommandée

Provider est la solution de gestion d’état recommandée par l’équipe Flutter. Elle utilise le pattern InheritedWidget de manière simplifiée.

Installation

Ajoutez Provider à votre pubspec.yaml :

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.1.1

Exemple avec ChangeNotifier

// Définition du modèle
class CartModel extends ChangeNotifier {
  final List<Item> _items = [];

  List<Item> get items => List.unmodifiable(_items);

  int get totalPrice => _items.fold(0, (sum, item) => sum + item.price);

  void add(Item item) {
    _items.add(item);
    notifyListeners(); // Notifie les widgets qui écoutent
  }

  void remove(Item item) {
    _items.remove(item);
    notifyListeners();
  }
}
// Utilisation dans l'application
void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => CartModel(),
      child: const MyApp(),
    ),
  );
}

// Dans un widget
class CartScreen extends StatelessWidget {
  const CartScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Consumer<CartModel>(
      builder: (context, cart, child) {
        return Text('Total: ${cart.totalPrice} €');
      },
    );
  }
}

3. Riverpod - Provider amélioré

Riverpod est une réécriture complète de Provider qui résout certaines de ses limitations.

// Définition d'un provider
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
  return CounterNotifier();
});

class CounterNotifier extends StateNotifier<int> {
  CounterNotifier() : super(0);

  void increment() => state++;
  void decrement() => state--;
}
// Utilisation avec ConsumerWidget
class CounterScreen extends ConsumerWidget {
  const CounterScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);

    return Scaffold(
      body: Center(
        child: Text('Count: $count'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => ref.read(counterProvider.notifier).increment(),
        child: const Icon(Icons.add),
      ),
    );
  }
}

4. BLoC - Business Logic Component

Le pattern BLoC sépare la logique métier de l’interface utilisateur en utilisant des streams.

// Événements
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}
class DecrementEvent extends CounterEvent {}

// BLoC
class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0) {
    on<IncrementEvent>((event, emit) => emit(state + 1));
    on<DecrementEvent>((event, emit) => emit(state - 1));
  }
}
// Utilisation
class CounterPage extends StatelessWidget {
  const CounterPage({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<CounterBloc, int>(
      builder: (context, count) {
        return Column(
          children: [
            Text('$count'),
            Row(
              children: [
                IconButton(
                  icon: const Icon(Icons.remove),
                  onPressed: () => context.read<CounterBloc>().add(DecrementEvent()),
                ),
                IconButton(
                  icon: const Icon(Icons.add),
                  onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),
                ),
              ],
            ),
          ],
        );
      },
    );
  }
}

Tableau comparatif

SolutionComplexitéCas d’usageTestabilité
setStateFaibleÉtat local simpleMoyenne
ProviderMoyenneApps moyennesBonne
RiverpodMoyenneApps moyennes/grandesExcellente
BLoCÉlevéeApps complexesExcellente

Conclusion

Le choix de la solution de gestion d’état dépend de plusieurs facteurs :

  1. La taille de votre application - Pour les petites apps, setState ou Provider suffisent
  2. La complexité de votre état - Plus l’état est complexe, plus BLoC ou Riverpod sont appropriés
  3. L’expérience de votre équipe - Choisissez une solution que votre équipe maîtrise

Mon conseil : commencez simple avec setState et Provider, puis migrez vers Riverpod ou BLoC si le besoin s’en fait sentir.


Cet article vous a été utile ? N’hésitez pas à le partager et à me suivre sur Twitter pour plus de contenu sur Flutter !