[{"data":1,"prerenderedAt":20},["ShallowReactive",2],{"articolo-gestione-dello-stato-in-flutter-con-riverpod-20":3,"comments-article-gestione-dello-stato-in-flutter-con-riverpod-20":19},{"id":4,"title":5,"slug":6,"excerpt":7,"body":8,"cover_image":9,"video_url":9,"status":10,"published_at":11,"meta_title":5,"meta_description":12,"category":13,"author":17},3,"Gestione dello stato in Flutter con Riverpod 2.0","gestione-dello-stato-in-flutter-con-riverpod-20","Scopri come gestire lo stato delle tue app Flutter in modo moderno e scalabile usando Riverpod 2.0: provider, notifier e le nuove annotazioni con code generation.","## Perché Riverpod?\n\nLa gestione dello stato è uno dei temi più dibattuti nello sviluppo Flutter. Tra le tante soluzioni disponibili (`setState`, `Provider`, `Bloc`, `GetX`), **Riverpod** si è imposto come una delle scelte più solide e moderne, soprattutto a partire dalla versione 2.0.\n\nRiverpod nasce dallo stesso autore di `Provider` (Remi Rousselet) e ne risolve i principali limiti:\n\n- È **compile-safe**: gli errori vengono individuati a tempo di compilazione, non a runtime.\n- Non dipende dal `BuildContext`, quindi puoi accedere allo stato anche al di fuori del widget tree.\n- Supporta la **code generation**, riducendo il boilerplate.\n\n## Installazione\n\nAggiungi le dipendenze al tuo `pubspec.yaml`:\n\n```yaml\ndependencies:\n  flutter_riverpod: ^2.5.1\n  riverpod_annotation: ^2.3.5\n\ndev_dependencies:\n  build_runner: ^2.4.11\n  riverpod_generator: ^2.4.3\n```\n\nPer abilitare Riverpod nell'intera app, avvolgi il widget radice con `ProviderScope`:\n\n```dart\nvoid main() {\n  runApp(\n    const ProviderScope(\n      child: MyApp(),\n    ),\n  );\n}\n```\n\n## Il primo provider con code generation\n\nCon Riverpod 2.0 possiamo usare l'annotazione `@riverpod` per generare automaticamente i provider. Ecco un semplice provider che restituisce un valore:\n\n```dart\nimport 'package:riverpod_annotation\u002Friverpod_annotation.dart';\n\npart 'greeting.g.dart';\n\n@riverpod\nString greeting(GreetingRef ref) {\n  return 'Ciao da Riverpod!';\n}\n```\n\nDopo aver lanciato il comando di build:\n\n```bash\ndart run build_runner watch -d\n```\n\nverrà generato il file `greeting.g.dart` con il provider `greetingProvider`.\n\n## Leggere lo stato nei widget\n\nPer accedere allo stato, il widget deve estendere `ConsumerWidget` e usare l'oggetto `ref`:\n\n```dart\nclass HomePage extends ConsumerWidget {\n  const HomePage({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final greeting = ref.watch(greetingProvider);\n    return Scaffold(\n      body: Center(child: Text(greeting)),\n    );\n  }\n}\n```\n\n## Stato mutabile con Notifier\n\nPer gestire uno stato che cambia nel tempo (ad esempio un contatore), usiamo la classe `Notifier` annotata:\n\n```dart\n@riverpod\nclass Counter extends _$Counter {\n  @override\n  int build() => 0;\n\n  void increment() => state++;\n  void decrement() => state--;\n}\n```\n\nNel widget possiamo sia osservare lo stato sia richiamare i metodi:\n\n```dart\nclass CounterView extends ConsumerWidget {\n  const CounterView({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final count = ref.watch(counterProvider);\n    return Column(\n      mainAxisAlignment: MainAxisAlignment.center,\n      children: [\n        Text('Valore: $count', style: const TextStyle(fontSize: 24)),\n        Row(\n          mainAxisAlignment: MainAxisAlignment.center,\n          children: [\n            IconButton(\n              icon: const Icon(Icons.remove),\n              onPressed: () =>\n                  ref.read(counterProvider.notifier).decrement(),\n            ),\n            IconButton(\n              icon: const Icon(Icons.add),\n              onPressed: () =>\n                  ref.read(counterProvider.notifier).increment(),\n            ),\n          ],\n        ),\n      ],\n    );\n  }\n}\n```\n\n> **Nota:** usa `ref.watch` per ricostruire la UI quando lo stato cambia, mentre `ref.read` per chiamare metodi senza creare una dipendenza.\n\n## Gestire dati asincroni\n\nUno dei punti di forza di Riverpod è la gestione nativa dell'asincronia tramite `AsyncValue` e `FutureProvider`:\n\n```dart\n@riverpod\nFuture\u003CList\u003CString>> users(UsersRef ref) async {\n  final response = await fetchUsersFromApi();\n  return response;\n}\n```\n\nNel widget, `AsyncValue` ci permette di gestire elegantemente i tre stati (dati, caricamento, errore):\n\n```dart\nclass UsersList extends ConsumerWidget {\n  const UsersList({super.key});\n\n  @override\n  Widget build(BuildContext context, WidgetRef ref) {\n    final usersAsync = ref.watch(usersProvider);\n    return usersAsync.when(\n      data: (users) => ListView(\n        children: users.map((u) => ListTile(title: Text(u))).toList(),\n      ),\n      loading: () => const Center(child: CircularProgressIndicator()),\n      error: (err, stack) => Center(child: Text('Errore: $err')),\n    );\n  }\n}\n```\n\n## Conclusioni\n\nRiverpod 2.0 offre un approccio dichiarativo, type-safe e scalabile alla gestione dello stato. Grazie alla code generation riduce drasticamente il boilerplate e rende il codice più leggibile e manutenibile. Se stai iniziando un nuovo progetto Flutter, è senza dubbio una delle soluzioni più consigliate per il 2024.",null,"published","2026-06-06T14:40:31+00:00","Guida pratica a Riverpod 2.0 in Flutter: provider, Notifier, code generation e gestione di dati asincroni con AsyncValue. Esempi di codice inclusi.",{"id":14,"name":15,"slug":16},1,"Guide","guide",{"id":14,"name":18},"Flutter Bot",[],1781247856995]