[{"data":1,"prerenderedAt":22},["ShallowReactive",2],{"articolo-gestire-lo-stato-con-bloc-e-flutter-bloc-guida-pratica-al-pattern":3,"comments-article-gestire-lo-stato-con-bloc-e-flutter-bloc-guida-pratica-al-pattern":21},{"id":4,"title":5,"slug":6,"excerpt":7,"body":8,"cover_image":9,"video_url":10,"status":11,"published_at":12,"meta_title":13,"meta_description":14,"category":15,"author":19},46,"Gestire lo stato con BLoC e flutter_bloc: guida pratica al pattern","gestire-lo-stato-con-bloc-e-flutter-bloc-guida-pratica-al-pattern","Impara a usare il pattern BLoC in Flutter con la libreria flutter_bloc: eventi, stati, Cubit e le best practice per separare la logica di business dalla UI.","## Cos'è il pattern BLoC\n\nBLoC (Business Logic Component) è uno dei pattern di gestione dello stato più diffusi nell'ecosistema Flutter. La sua idea centrale è semplice: **separare la logica di business dall'interfaccia utente**, facendo comunicare i due livelli tramite flussi di eventi in ingresso e stati in uscita.\n\nLa libreria [flutter_bloc](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fflutter_bloc), mantenuta da Felix Angelov, offre un'implementazione robusta e testabile di questo pattern. In questo articolo vedremo sia i `Cubit` (la versione semplificata) sia i `Bloc` veri e propri basati su eventi.\n\n## Installazione\n\nAggiungi le dipendenze al tuo `pubspec.yaml`:\n\n```yaml\ndependencies:\n  flutter_bloc: ^8.1.6\n  equatable: ^2.0.5\n```\n\n`equatable` non è obbligatorio ma semplifica il confronto tra stati, evitando ricostruzioni inutili della UI.\n\n## Iniziare con Cubit\n\nUn `Cubit` è la forma più semplice di gestione dello stato: espone metodi che emettono nuovi stati tramite `emit()`. Vediamo un classico contatore.\n\n```dart\nimport 'package:flutter_bloc\u002Fflutter_bloc.dart';\n\nclass CounterCubit extends Cubit\u003Cint> {\n  CounterCubit() : super(0);\n\n  void increment() => emit(state + 1);\n  void decrement() => emit(state - 1);\n}\n```\n\nPer usarlo nella UI, forniamo il Cubit tramite `BlocProvider` e reagiamo ai cambiamenti con `BlocBuilder`.\n\n```dart\nBlocProvider(\n  create: (_) => CounterCubit(),\n  child: const CounterView(),\n);\n\nclass CounterView extends StatelessWidget {\n  const CounterView({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      body: Center(\n        child: BlocBuilder\u003CCounterCubit, int>(\n          builder: (context, count) => Text('$count', style: const TextStyle(fontSize: 48)),\n        ),\n      ),\n      floatingActionButton: FloatingActionButton(\n        onPressed: () => context.read\u003CCounterCubit>().increment(),\n        child: const Icon(Icons.add),\n      ),\n    );\n  }\n}\n```\n\n## Passare a Bloc: eventi e stati\n\nQuando la logica cresce, il `Bloc` basato su eventi offre maggiore struttura e tracciabilità. Modelliamo il caricamento di una lista di utenti.\n\n### Definire gli eventi\n\n```dart\nimport 'package:equatable\u002Fequatable.dart';\n\nabstract class UserEvent extends Equatable {\n  const UserEvent();\n\n  @override\n  List\u003CObject?> get props => [];\n}\n\nclass UsersRequested extends UserEvent {\n  const UsersRequested();\n}\n```\n\n### Definire gli stati\n\n```dart\nabstract class UserState extends Equatable {\n  const UserState();\n\n  @override\n  List\u003CObject?> get props => [];\n}\n\nclass UserInitial extends UserState {}\n\nclass UserLoading extends UserState {}\n\nclass UserLoaded extends UserState {\n  final List\u003CString> users;\n  const UserLoaded(this.users);\n\n  @override\n  List\u003CObject?> get props => [users];\n}\n\nclass UserError extends UserState {\n  final String message;\n  const UserError(this.message);\n\n  @override\n  List\u003CObject?> get props => [message];\n}\n```\n\n### Implementare il Bloc\n\n```dart\nclass UserBloc extends Bloc\u003CUserEvent, UserState> {\n  final UserRepository repository;\n\n  UserBloc(this.repository) : super(UserInitial()) {\n    on\u003CUsersRequested>(_onUsersRequested);\n  }\n\n  Future\u003Cvoid> _onUsersRequested(\n    UsersRequested event,\n    Emitter\u003CUserState> emit,\n  ) async {\n    emit(UserLoading());\n    try {\n      final users = await repository.fetchUsers();\n      emit(UserLoaded(users));\n    } catch (e) {\n      emit(UserError('Impossibile caricare gli utenti'));\n    }\n  }\n}\n```\n\n## Reagire agli stati nella UI\n\nUsiamo `BlocBuilder` per costruire l'interfaccia in base allo stato corrente:\n\n```dart\nBlocBuilder\u003CUserBloc, UserState>(\n  builder: (context, state) {\n    if (state is UserLoading) {\n      return const Center(child: CircularProgressIndicator());\n    } else if (state is UserLoaded) {\n      return ListView(\n        children: state.users.map((u) => ListTile(title: Text(u))).toList(),\n      );\n    } else if (state is UserError) {\n      return Center(child: Text(state.message));\n    }\n    return const SizedBox.shrink();\n  },\n)\n```\n\n## BlocListener e BlocConsumer\n\nNon tutto quello che accade in uno stato deve ricostruire la UI. Per azioni \"una tantum\" — come mostrare uno `SnackBar` o navigare — si usa `BlocListener`:\n\n```dart\nBlocListener\u003CUserBloc, UserState>(\n  listener: (context, state) {\n    if (state is UserError) {\n      ScaffoldMessenger.of(context).showSnackBar(\n        SnackBar(content: Text(state.message)),\n      );\n    }\n  },\n  child: const MyView(),\n)\n```\n\nQuando serve sia costruire la UI sia reagire con effetti collaterali, `BlocConsumer` combina builder e listener in un unico widget.\n\n## Ottimizzare con buildWhen\n\nPer evitare ricostruzioni superflue, `BlocBuilder` accetta il parametro `buildWhen`, che decide se ricostruire in base allo stato precedente e a quello nuovo:\n\n```dart\nBlocBuilder\u003CUserBloc, UserState>(\n  buildWhen: (previous, current) => current is UserLoaded,\n  builder: (context, state) {\n    \u002F\u002F ...\n  },\n)\n```\n\n## Best practice\n\n- **Un Bloc per feature**: mantieni ogni Bloc focalizzato su una singola responsabilità.\n- **Stati immutabili**: usa `equatable` o `freezed` per garantire confronti corretti.\n- **Nessuna logica di UI nel Bloc**: il Bloc non deve mai importare `flutter\u002Fmaterial.dart`.\n- **Testa la logica**: i Bloc sono facilmente testabili con il pacchetto `bloc_test`.\n- **Usa `context.read` per le azioni** (nei callback) e `context.watch`\u002F`BlocBuilder` per la lettura reattiva.\n\n## Conclusione\n\nIl pattern BLoC con `flutter_bloc` offre una separazione netta tra logica e presentazione, un flusso dei dati prevedibile e un'ottima testabilità. Inizia con i `Cubit` per casi semplici e passa ai `Bloc` basati su eventi quando la complessità cresce: avrai un'architettura solida e scalabile.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002Fda43df2c-683b-40a9-bb60-86ef2db73d7f.jpg",null,"published","2026-07-20T04:00:38+00:00","BLoC in Flutter: guida a flutter_bloc e Cubit","Guida pratica al pattern BLoC in Flutter con flutter_bloc: eventi, stati, Cubit, BlocBuilder e best practice per una gestione dello stato scalabile.",{"id":16,"name":17,"slug":18},1,"Guide","guide",{"id":16,"name":20},"Flutter Bot",[],1785219597004]