BLoC — cos'è, Business Logic Component in Flutter

Autore: IT Sectr Pubblicato: 2026-02-19 Tempo di lettura: 7 min

BLoC (Business Logic Component) — un pattern di gestione dello stato per Flutter, presentato da Google nel 2018 al DartConf. BLoC separa la logica di business dall'interfaccia utente attraverso flussi reattivi (Stream): l'UI invia un Event, BLoC lo elabora e restituisce un nuovo State tramite Stream. Secondo pub.dev, il pacchetto flutter_bloc ha raccolto oltre 11 mila like ed è utilizzato in migliaia di applicazioni Flutter.

Punti chiave

  • Event — segnale di ingresso che descrive un'azione: pressione di un pulsante, caricamento dati
  • State — stato di uscita dell'UI: dati caricati, errore, caricamento
  • Bloc — classe principale che riceve Event e restituisce State tramite Stream
  • Cubit — versione semplificata di Bloc senza Event, che chiama funzioni direttamente
  • BlocProvider — widget Flutter per iniettare Bloc nell'albero dei widget

Cos'è BLoC?

BLoC (Business Logic Component) — un pattern architetturale per Flutter in cui la logica di business viene estratta in una classe separata, isolata dall'UI. BLoC riceve dati di ingresso attraverso un flusso di eventi (Event) e produce dati di uscita attraverso un flusso di stati (State). Lo strato di presentazione (Widget) si iscrive solo al flusso State e renderizza l'UI, senza mai eseguire direttamente la logica di business.

Il concetto BLoC si basa sulla programmazione reattiva e sul pattern Observer. Ogni componente BLoC è un modulo separato con un contratto chiaro: un insieme noto di Event (cosa può accadere) e un insieme noto di State (cosa può essere visualizzato). Uno sviluppatore non può modificare "accidentalmente" lo stato dall'UI — solo attraverso un Event specifico. Questo rende il codice prevedibile e testabile.

Secondo il sondaggio Flutter Community 2025, BLoC occupa il secondo posto in popolarità tra le soluzioni di gestione dello stato in Flutter dopo Provider. Vantaggi principali: tipizzazione forte, isolamento della logica, supporto integrato di Stream, ricco ecosistema di utilità (BlocProvider, BlocListener, BlocSelector).

Architettura BLoC: Event → Bloc → State

L'architettura BLoC è costruita attorno a tre entità: Event (ingresso), Bloc (gestore) e State (uscita). Il Widget invia un Event tramite il metodo add(). Bloc riceve l'Event nel metodo mapEventToState o on<Event>, esegue la logica di business e emette un nuovo State tramite yield. Il Widget riceve lo State attraverso uno Stream e si ricostruisce.

Dart
abstract class CounterEvent {}

class Increment extends CounterEvent {}
class Decrement extends CounterEvent {}

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0);

  @override
  Stream<int> mapEventToState(CounterEvent event) async* {
    if (event is Increment) {
      yield state + 1;
    } else if (event is Decrement) {
      yield state - 1;
    }
  }
}

Sicurezza dei tipi: Bloc è parametrizzato con due tipi — Event e State. Il compilatore Dart verifica che il Widget chiami solo Event dichiarati e che Bloc restituisca solo State dichiarati. Gli errori a runtime come "Azione sconosciuta" sono eliminati.

Close e Dispose: Bloc implementa l'interfaccia Closeable. Quando un widget viene distrutto, Bloc chiude automaticamente lo Stream tramite il metodo close(). Le perdite di sottoscrizioni reattive sono impossibili — BlocProvider gestisce il ciclo di vita di Bloc, legandolo a una route o pagina.

Bloc e Cubit: confronto

Cubit è un'implementazione semplificata di Bloc senza Event, introdotta nel pacchetto flutter_bloc 6.0. Cubit dichiara metodi direttamente invece di classi Event: increment(), fetchData(). Internamente, Cubit utilizza lo stesso meccanismo basato su Stream ma nasconde lo strato Event. Questo riduce il boilerplate del 40-50% per scenari semplici.

CaratteristicaBlocCubit
Classi EventObbligatorieNon necessarie
BoilerplateAltoBasso
Tracciamento azioniTramite tipo EventSolo nome metodo
Ideale perScenari complessiStati semplici
AnaliticaAutomatica per EventManuale

Quando scegliere Cubit: stato con 2-3 varianti (loading, loaded, error), moduli semplici, contatori, stati UI (aperto/chiuso). Quando scegliere Bloc: logica di business complessa con molte azioni: elaborazione ordini, autorizzazione, sincronizzazione dati. Bloc fornisce tracciamento dettagliato di ogni azione tramite Event — ogni chiamata viene registrata in BlocObserver.

BlocObserver — un osservatore globale che traccia tutti i Bloc e Cubit nell'applicazione. Permette di registrare Event, State, errori e transizioni. Basta collegare un'istanza: Bloc.observer = AppBlocObserver(), e tutto il tracciamento dello stato dell'applicazione è disponibile centralmente.

BlocProvider e BlocBuilder

BlocProvider — un InheritedWidget da flutter_bloc che fornisce un Bloc ai widget figli. Quando un widget viene inizializzato, BlocProvider crea un Bloc, e quando viene distrutto — lo chiude automaticamente tramite close(). BlocProvider può essere posizionato a livello di MaterialApp (Bloc globale) o a livello di una route specifica (Bloc locale).

Dart
BlocProvider(
  create: (context) => CounterBloc(),
  child: Column(
    children: [
      BlocBuilder<CounterBloc, int>(
        builder: (context, state) => Text('$state'),
      ),
      ElevatedButton(
        onPressed: () => context.read<CounterBloc>().add(Increment()),
        child: Text('+'),
      ),
    ],
  ),
)

BlocBuilder — un widget che ricostruisce l'UI ad ogni nuovo State. BlocListener — per effetti collaterali (elaborare uno State una volta, senza ricostruire l'UI): mostrare uno SnackBar, navigare verso un'altra schermata. BlocConsumer — una combinazione di Builder e Listener per casi in cui sono necessari sia la ricostruzione che l'effetto collaterale. BlocSelector — per ricostruzione selettiva solo quando un campo specifico dello State cambia.

MultiBlocProvider — un widget per BlocProvider annidati senza aumentare i livelli di annidamento. Un'applicazione Flutter con 10-15 Bloc utilizza MultiBlocProvider a livello radice per registrare tutti i Bloc disponibili per l'intera applicazione: AuthenticationBloc, CartBloc, SettingsBloc.

Testare BLoC

BLoC viene testato in isolamento senza widget Flutter. Basta importare il pacchetto Dart flutter_test e il pacchetto bloc_test. Lo scenario di test: creare un Bloc, aggiungere un Event, verificare lo State. blocTest — un'utilità che automatizza la sequenza: build → act → expect.

Dart
blocTest<CounterBloc, int>(
  'emits [1] when Increment is added',
  build: () => CounterBloc(),
  act: (bloc) => bloc.add(Increment()),
  expect: () => [1],
)

Mocking: Un Bloc che dipende da un repository o API viene testato con mock tramite mocktail. Il repository viene mockato a livello di astrazione, e il Bloc riceve le dipendenze mockate attraverso il costruttore. Hydrated Bloc — un'estensione per la persistenza/ripristino automatico dello stato in memoria locale. Viene testato con HydratedBlocStorage e un archivio di file temporaneo.

BLoC in produzione

Cartelle e file: una struttura tipica di progetto Flutter con BLoC: bloc/counter_bloc.dart, bloc/counter_event.dart, bloc/counter_state.dart. Per 30+ schermate, si consiglia il raggruppamento per funzionalità: features/auth/bloc/, features/cart/bloc/. Ogni Bloc è un file separato, ogni Event e State — o in file separati o in un file con il Bloc.

Prestazioni: BLoC non crea overhead per Stream vuoti. BlocBuilder usa buildWhen per filtrare le ricostruzioni — il widget si aggiorna solo quando una condizione specifica cambia. Close garantisce che i Bloc inattivi non consumino memoria. Secondo Flutter DevTools, BLoC aggiunge meno dell'1% alla dimensione del bundle.

Migrazione da Provider: BLoC coesiste facilmente con Provider nello stesso progetto. Migrazione graduale: prima sostituisci i Provider più complessi con Bloc, poi il resto. BlocProvider è compatibile con l'albero Provider: i vecchi widget possono usare Provider, i nuovi — BlocProvider, all'interno della stessa applicazione.

Domande frequenti

In che modo BLoC si differenzia da Provider in Flutter?

BLoC usa Event + Stream per l'isolamento della logica di business e la tipizzazione forte. Provider è un wrapper attorno a InheritedWidget per l'iniezione di dipendenze semplice e ChangeNotifier. BLoC è migliore per scenari complessi con molti stati, Provider — per lo stato UI locale. BLoC richiede più boilerplate ma offre tracciabilità completa tramite Event.

Cos'è Hydrated Bloc?

Hydrated Bloc è un'estensione del pacchetto hydrated_bloc che salva automaticamente l'ultimo State in memoria locale (Hive per impostazione predefinita). Quando l'applicazione viene riavviata, Bloc ripristina lo stato salvato invece di quello iniziale. Questo risolve il problema di persistenza senza chiamate di salvataggio manuali: login, carrello, impostazioni vengono salvati automaticamente tra le sessioni.

Come gestire gli errori in BLoC?

Un errore in BLoC viene gestito tramite try-catch all'interno di mapEventToState o on<Event>. In caso di errore, Bloc restituisce uno State di errore: yield LoadError(error.message). Sull'UI, BlocListener o BlocConsumer verifica lo State per il tipo di errore e mostra uno SnackBar o un dialogo. BlocObserver registra globalmente tutte le eccezioni non gestite.

BLoC può essere usato con altri framework?

BLoC è un pattern specifico di Flutter poiché utilizza Dart Stream e widget Flutter. Il concetto Event → Bloc → State può essere adattato per AngularDart e Server-side Dart, ma l'ecosistema principale (BlocProvider, BlocBuilder, BlocObserver) è legato a Flutter. Per React Native, usa Redux o MobX; per SwiftUI, usa Combine + MVVM.

Cosa scegliere: Bloc o Cubit?

Cubit — per stati semplici (contatore, toggle, modulo con 2-3 campi). Bloc — per logica complessa (feed di notizie, elaborazione ordini, autorizzazione). La regola principale: se hai bisogno del tracciamento di ogni azione (Event) per analisi o debug — scegli Bloc. Se i metodi che cambiano lo stato sono sufficienti — scegli Cubit. Entrambi i pattern possono coesistere nello stesso progetto.

Riepilogo

  • BLoC — pattern di gestione dello stato Flutter tramite Event → Stream → State
  • Event — azione (premere, caricare), State — reazione (dati, errore, caricamento)
  • Cubit — versione semplificata senza Event, fino al 50% meno boilerplate
  • BlocProvider — iniezione di Bloc nell'albero dei widget con chiusura automatica
  • BlocObserver — monitoraggio globale di tutti i Bloc e Cubit nell'applicazione
  • Hydrated Bloc — persistenza automatica dello stato tramite Hive
  • blocTest — utilità per test unitari di Bloc isolati da Flutter

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche