f in x
State Management in Flutter: Provider, Riverpod e Bloc — Guida Operativa per Sviluppatori
> cd .. / HUB_EDITORIALE > Visualizza in Inglese
Sviluppo di siti web

State Management in Flutter: Provider, Riverpod e Bloc — Guida Operativa per Sviluppatori

[2026-06-20] Author: Ing. Calogero Bono

Il cliente ti mostra il prototipo dell'app. Funziona tutto, sembra perfetto. Poi aggiungi un bottone, cambia un dato, e l'interfaccia non si aggiorna. Oppure, peggio, il conto della spesa si azzera da solo. Benvenuto nel problema più classico di Flutter: gestire lo stato.

Se sei un team che sviluppa app mobile, sai che lo state management non è un dettaglio tecnico: è l'architettura su cui si regge tutto il resto. Sbagliare qui significa codice fragile, bug impossibili da riprodurre e tempi di sviluppo che lievitano. Noi, di Meteora Web, lo vediamo ogni giorno nei progetti che ci arrivano da rifare. App con Provider usato male, Bloc sovraingegnerizzato, o peggio, stato globale buttato in variabili mutabili.

In questa guida non ti diamo una ricetta astratta. Ti mostriamo Provider, Riverpod e Bloc con esempi reali, il contesto in cui ciascuno brilla, e come scegliere senza rimpianti. Più avanti trovi link alla nostra pillar sullo sviluppo con Flutter, se vuoi il quadro completo.

Cos'è lo state management? (e perché ti costa soldi se lo ignori)

Lo stato è l'insieme dei dati che cambiano nel tempo: il carrello di un e-commerce, la lista dei post letti, la posizione GPS. In Flutter, ogni Widget può avere un suo stato, ma quando due schermate devono condividere gli stessi dati, il caos regna. Senza un pattern di state management, finisci per:

  • Passare dati di mano in mano nei costruttori (prop drilling).
  • Creare variabili globali che chiunque può modificare.
  • Ricaricare dati inutili da API perché non sai se sono aggiornati.

Il risultato? Un'app che va in produzione con bug di sincronizzazione, utenti che perdono dati e recensioni a una stella. Ogni ora spesa a inseguire questi bug è un'ora che non hai speso a migliorare il prodotto. Per questo il dilemma Provider vs Riverpod vs Bloc non è solo tecnico: è economico. Scegliere lo strumento giusto significa codice più prevedibile, manutenibile e veloce da sviluppare.

Sponsored Protocol

Provider — il primo passo (e il più semplice)

Provider è la soluzione ufficiale raccomandata da Google per molto tempo. Funziona con un modello a dipendenza e notifica: un oggetto (ChangeNotifier) espone dati e metodi, e i Widget si iscrivono per ricevere aggiornamenti.

Quando usarlo

Provider va bene per app di piccole-medie dimensioni, con stato non troppo complesso e team ridotti. Se hai un e-commerce con carrello, preferiti e utente loggato, ci stai dentro. Se devi orchestrare decine di flussi asincroni e validazioni incrociate, meglio guardare avanti.

Esempio pratico: contatore con Provider

Un classico, ma ti fa capire il meccanismo:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

// 1. Modello dello stato
class Counter extends ChangeNotifier {
  int _count = 0;
  int get count => _count;

  void increment() {
    _count++;
    notifyListeners(); // avvisa i Widget
  }
}

// 2. Forniamo il modello all'albero
void main() {
  runApp(
    ChangeNotifierProvider(
      create: (_) => Counter(),
      child: MyApp(),
    ),
  );
}

// 3. Widget che consuma
class CounterLabel extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = context.watch<Counter>();
    return Text('${counter.count}');
  }
}

Cosa notare: notifyListeners() è un'arma a doppio taglio. Se lo chiami troppo spesso, ri-costruisci Widget non necessari. Provider non ha un modo nativo per gestire la disposizione automatica (se non tramite Dispose manuale).

Sponsored Protocol

Riverpod — Provider senza le catene

Riverpod nasce proprio dai limiti di Provider. Stessa filosofia, ma senza dipendenza dal context di Flutter. Ogni provider è un oggetto globale dichiarato fuori dall'albero dei Widget, il che significa:

  • Puoi testare e accedere allo stato senza avere un BuildContext.
  • I provider si ricreano automaticamente quando non servono più (grazie al sistema di ref-counting).
  • Supporto nativo per async, caching e combinazione di più provider.

Quando usarlo

Riverpod è oggi la scelta migliore per la maggior parte delle app Flutter nuove. È flessibile, leggero e scalabile. Noi lo consigliamo per progetti che guardano al medio termine: preparati a crescere senza dover riscrivere tutto.

Esempio: fetch di dati con Riverpod

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;

// 1. Provider asincrono che fa una chiamata API
final apiDataProvider = FutureProvider<List<String>>((ref) async {
  final response = await http.get(Uri.parse('https://api.example.com/items'));
  if (response.statusCode != 200) throw Exception('Errore');
  return (response.body as List).cast<String>();
});

// 2. Widget consumer
class DataList extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final asyncData = ref.watch(apiDataProvider);
    return asyncData.when(
      loading: () => CircularProgressIndicator(),
      error: (err, stack) => Text('Errore: $err'),
      data: (items) => ListView.builder(
        itemCount: items.length,
        itemBuilder: (ctx, i) => ListTile(title: Text(items[i])),
      ),
    );
  }
}

Nota come FutureProvider gestisce automaticamente loading e catch. Nessun setState, nessuna notifica manuale. Il dato viene richiesto solo quando c'è almeno un Widget in ascolto.

Sponsored Protocol

Bloc — l'enterprise a prova di proiettile

Bloc (Business Logic Component) è il pattern più strutturato. Si basa su Eventi e Stati: l'utente (o il sistema) invia un Evento, il Bloc lo processa e produce un nuovo Stato. Tutto è immutabile e separato dalla UI.

Quando usarlo

Bloc eccelle in progetti complessi: app con decine di schermate, flussi di autenticazione multi-step, moduli con validazioni incrociate. Se il tuo team è numeroso, Bloc impone una disciplina che aiuta a mantenere il codice leggibile. Lo svantaggio? Più boilerplate. Per una app semplice, è un cannone per sparare a una mosca.

Esempio: login con Bloc

// eventi
abstract class AuthEvent {}
class LoginPressed extends AuthEvent {
  final String email, password;
  LoginPressed(this.email, this.password);
}

// stati
abstract class AuthState {}
class AuthInitial extends AuthState {}
class AuthLoading extends AuthState {}
class AuthSuccess extends AuthState {}
class AuthFailure extends AuthState {
  final String message;
  AuthFailure(this.message);
}

// Bloc
class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final AuthRepository repo;
  AuthBloc(this.repo) : super(AuthInitial()) {
    on<LoginPressed>((event, emit) async {
      emit(AuthLoading());
      try {
        await repo.login(event.email, event.password);
        emit(AuthSuccess());
      } catch (e) {
        emit(AuthFailure(e.toString()));
      }
    });
  }
}

// UI – BlocProvider e BlocBuilder
BlocProvider(
  create: (_) => AuthBloc(repo),
  child: BlocBuilder<AuthBloc, AuthState>(
    builder: (context, state) {
      if (state is AuthLoading) return CircularProgressIndicator();
      if (state is AuthFailure) return Text(state.message);
      if (state is AuthSuccess) return Text('Benvenuto!');
      return LoginForm();
    },
  ),
);

Ogni evento produce un nuovo stato. La UI è una pura funzione dello stato: più facile da testare, più facile da debuggare. Con Bloc puoi anche usare BlocListener per azioni una tantum (es. navigare dopo login).

Sponsored Protocol

Come scegliere: una decisione che costa meno del refactoring

Ecco una regola pratica che usiamo nei nostri progetti:

  • App prototipo o con meno di 10 schermate → Provider va bene, ma se parti da zero meglio Riverpod.
  • App media (es. e-commerce, social, dashboard) → Riverpod. Meno boilerplate di Bloc, più potente di Provider.
  • App enterprise, multi-team, requisiti complessi → Bloc. La struttura paga quando il progetto dura anni.

Non mischiare i pattern in uno stesso progetto a meno di non sapere esattamente cosa stai facendo. Noi abbiamo visto codebase con Provider + Bloc + GetX convivere: un incubo.

Sponsored Protocol

In sintesi — cosa fare adesso

  1. Se stai iniziando un nuovo progetto Flutter, usa Riverpod. È la scelta più bilanciata tra semplicità e potenza. Studia la documentazione ufficiale: riverpod.dev.
  2. Se hai già un progetto con Provider, non riscrivere tutto di corsa. Migra gradualmente un modulo alla volta verso Riverpod (esiste un pacchetto di bridge).
  3. Se il tuo team arriva da Bloc e l'app è stabile, resta su Bloc. La curva di apprendimento è già stata pagata. Investi in una buona struttura di cartelle e test.
  4. Leggi la nostra pillare principale su Flutter per capire il quadro completo dello sviluppo cross-platform: App Mobile con Flutter — La Pillar Definitiva.
  5. Testa sempre lo stato. Scrivi unit test per i tuoi provider o bloc prima di scrivere la UI. Con Riverpod e Bloc è semplice e ti evita regressioni.

Non esiste la soluzione perfetta per tutti i progetti. Ma esiste la soluzione sbagliata per il tuo: quella che scegli senza ragionare sul perché. Noi di Meteora Web abbiamo scelto Riverpod come standard per la nostra piattaforma proprietaria di gestione social, ma usiamo Bloc per moduli critici come la fatturazione. La scelta giusta è quella che conosci e che puoi sostenere nel tempo.

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere Informatico, co-fondatore di Meteora Web. Esperto in architetture software, sicurezza informatica e sviluppo sistemi scalabili.
[ Read Full Dossier ]

> METEORA_WEB // WEB AGENCY

Costruiamo la presenza digitale che la tua azienda merita.

Siti web, social, pubblicità online, e-commerce e hosting performante: ingegnerizzati con metodo da ingegneri informatici a Sciacca, per tutta Italia.

> MW_JOURNAL

> READ_ALL()