BLoC (Business Logic Component) — pattern ng pamamahala ng state para sa Flutter, ipinakilala ng Google noong 2018 sa DartConf. Pinaghihiwalay ng BLoC ang business logic mula sa user interface sa pamamagitan ng reaktibong mga stream (Stream): UI ay nagpapadala ng Event, pinoproseso ito ng BLoC at nagbabalik ng bagong State sa pamamagitan ng Stream. Ayon sa datos ng pub.dev, ang flutter_bloc package ay nakaipon ng mahigit 11 libong likes at ginagamit sa libu-libong Flutter application.
Mga Pangunahing Punto
BLoC (Business Logic Component) — pattern ng arkitektura para sa Flutter kung saan ang business logic ay inilalagay sa isang hiwalay na klase, nakahiwalay sa UI. Ang BLoC ay tumatanggap ng input data sa pamamagitan ng stream ng mga pangyayari (Event) at naglalabas ng output data sa pamamagitan ng stream ng mga state (State). Ang presentation layer (Widget) ay nag-subscribe lamang sa State stream at nagpapakita ng UI, hindi kailanman direktang nagpapatakbo ng business logic.
Ang konsepto ng BLoC ay batay sa reaktibong programming at pattern ng Observer. Bawat BLoC component ay hiwalay na modyul na may malinaw na kontrata: ang set ng Event (ano ang maaaring mangyari) at set ng State (ano ang maaaring ipakita) ay alam. Hindi maaaring "aksidenteng" baguhin ng developer ang state mula sa UI — sa pamamagitan lamang ng tiyak na Event. Ginagawa nitong predictable at testable ang code.
Ayon sa survey ng Flutter Community 2025, ang BLoC ay nasa ikalawang pwesto sa kasikatan sa mga solusyon sa pamamahala ng state sa Flutter pagkatapos ng Provider. Mga pangunahing bentahe: mahigpit na typification, paghihiwalay ng logic, built-in na suporta sa Stream, mayamang ecosystem ng mga utility (BlocProvider, BlocListener, BlocSelector).
Arkitektura ng BLoC ay binuo sa paligid ng tatlong entity: Event (input), Bloc (processor), at State (output). Ang Widget ay nagpapadala ng Event sa pamamagitan ng add() method. Tinatanggap ng Bloc ang Event sa mapEventToState o on<Event> method, isinasagawa ang business logic at naglalabas ng bagong State sa pamamagitan ng yield. Natatanggap ng Widget ang State sa pamamagitan ng Stream at nagre-render muli.
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;
}
}
}Kaligtasan ng tipo: Ang Bloc ay na-parameterize sa dalawang tipo — Event at State. Sinusuri ng Dart compiler na ang Widget ay tumatawag lamang ng mga idineklarang Event, at ang Bloc ay nagbabalik lamang ng mga idineklarang State. Ang mga runtime error na tulad ng "Hindi Kilalang Aksyon" ay hindi kasama.
Close at Dispose: Ang Bloc ay nagpapatupad ng Closeable interface. Kapag nawasak ang widget, awtomatikong isinasara ng Bloc ang Stream sa pamamagitan ng close() method. Ang pagtagas ng reaktibong subscription ay imposible — Pinamamahalaan ng BlocProvider ang lifecycle ng Bloc, iniuugnay ito sa isang ruta o pahina.
Cubit — pinasimpleng implementasyon ng Bloc na walang Event, ipinakilala sa flutter_bloc 6.0 package. Ang Cubit ay direktang nagdedeklara ng mga method sa halip na mga Event class: increment(), fetchData(). Sa loob, ginagamit ng Cubit ang parehong Stream-based na mekanismo, ngunit itinatago ang Event layer. Binabawasan nito ang boilerplate ng 40-50% para sa mga simpleng senaryo.
| Katangian | Bloc | Cubit |
|---|---|---|
| Mga Event class | Kailangan | Hindi kailangan |
| Boilerplate | Mataas | Mababa |
| Pagsubaybay ng aksyon | Sa pamamagitan ng Event type | Pangalan lang ng method |
| Angkop para sa | Mga komplikadong senaryo | Mga simpleng state |
| Analytics | Awtomatiko sa pamamagitan ng Event | Manual |
Kailan pumili ng Cubit: state na may 2-3 variant (loading, loaded, error), simpleng form, counter, UI state (bukas/sarado). Kailan Bloc: komplikadong business logic na may maraming aksyon: pag-checkout ng order, authentication, pag-sync ng datos. Nagbibigay ang Bloc ng detalyadong pagsubaybay ng bawat aksyon sa pamamagitan ng Event — bawat tawag ay nala-log sa BlocObserver.
BlocObserver — pandaigdigang tagamasid na sumusubaybay sa lahat ng Bloc at Cubit sa application. Pinapayagan ang pag-log ng Event, State, error, at transitions. Sapat na ikonekta ang isang instance: Bloc.observer = AppBlocObserver(), at ang buong pagsubaybay ng state ng application ay magagamit nang sentralisado.
BlocProvider — InheritedWidget mula sa flutter_bloc na nagbibigay ng Bloc sa mga child widget. Sa pagsisimula ng widget, gumagawa ang BlocProvider ng Bloc, at kapag nawasak — awtomatikong isinasara ito sa pamamagitan ng close(). Maaaring ilagay ang BlocProvider sa antas ng MaterialApp (global Bloc) o sa antas ng isang partikular na ruta (lokal na Bloc).
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 — widget na nagtatayo muli ng UI sa bawat bagong State. BlocListener — para sa side effects (isang beses na pagproseso ng State nang hindi itinatayong muli ang UI): pagpapakita ng SnackBar, pag-navigate sa ibang screen. BlocConsumer — kombinasyon ng Builder at Listener para sa mga kaso kung kailan kailangan ang parehong rebuild at side effect. BlocSelector — para sa pumipiling rebuild lamang kapag nagbago ang isang partikular na field ng State.
MultiBlocProvider — widget para sa nested BlocProvider nang hindi pinapataas ang nesting level. Ang Flutter application na may 10-15 Bloc ay gumagamit ng MultiBlocProvider sa root level para sa pagrehistro ng lahat ng Bloc na available sa buong application: AuthenticationBloc, CartBloc, SettingsBloc.
Ang BLoC ay sinusubok nang nakahiwalay nang walang Flutter widgets. Sapat na i-import ang Dart package na flutter_test at ang bloc_test package. Test scenario: gumawa ng Bloc, magdagdag ng Event, suriin ang State. blocTest — utility na nag-automate ng sequence: build → act → expect.
blocTest<CounterBloc, int>(
'emits [1] when Increment is added',
build: () => CounterBloc(),
act: (bloc) => bloc.add(Increment()),
expect: () => [1],
)Mocking: Ang BLoC na umaasa sa repository o API ay sinusubok gamit ang mga mock sa pamamagitan ng mocktail. Ang repository ay ni-mock sa abstraction level, natatanggap ng Bloc ang mga na-mock na dependencies sa pamamagitan ng constructor. Hydrated Bloc — extension para sa awtomatikong pag-save/pag-restore ng state sa lokal na storage. Sinusubok gamit ang HydratedBlocStorage at pansamantalang file storage.
Mga folder at file: tipikal na istraktura ng Flutter project na may BLoC: bloc/counter_bloc.dart, bloc/counter_event.dart, bloc/counter_state.dart. Para sa 30+ screen, inirerekomenda ang pagpapangkat ayon sa feature: features/auth/bloc/, features/cart/bloc/. Bawat Bloc — hiwalay na file, bawat Event at State — alinman sa magkahiwalay na file, o sa isang file kasama ang Bloc.
Pagganap: Ang BLoC ay hindi lumilikha ng overhead sa mga walang laman na Stream. Ang BlocBuilder ay gumagamit ng buildWhen para sa pag-filter ng mga rebuild — ang widget ay ina-update lamang kapag nagbago ang isang partikular na kondisyon. Ginagarantiya ng Close na ang mga hindi aktibong Bloc ay hindi kumokonsumo ng memorya. Ayon sa Flutter DevTools, ang BLoC ay nagdaragdag ng mas mababa sa 1% sa laki ng bundle.
Migrasyon mula sa Provider: Ang BLoC ay madaling nabubuhay kasama ng Provider sa parehong proyekto. Gradual na migrasyon: una ang pinakakomplikadong Provider ay pinapalitan ng Bloc, pagkatapos ang iba pa. Ang BlocProvider ay compatible sa Provider tree: ang mga lumang widget ay maaaring gumamit ng Provider, ang mga bago — BlocProvider, sa iisang application.
Mga Madalas Itanong
BLoC ay gumagamit ng Event + Stream para sa paghihiwalay ng business logic at mahigpit na typification. Provider — balot sa ibabaw ng InheritedWidget para sa simpleng dependency injection at ChangeNotifier. Ang BLoC ay mas angkop para sa komplikadong senaryo na may maraming state, Provider — para sa lokal na UI state. Ang BLoC ay nangangailangan ng mas maraming boilerplate, ngunit nagbibigay ng kumpletong pagsubaybay sa pamamagitan ng Event.
Hydrated Bloc — extension mula sa hydrated_bloc package na awtomatikong nagse-save ng huling State sa lokal na storage (default Hive). Kapag nag-restart ang application, pinapanumbalik ng Bloc ang naka-save na state sa halip na paunang state. Nalulutas nito ang problema ng persistency nang walang manual na pag-save: login, cart, setting ay awtomatikong nase-save sa pagitan ng mga session.
Ang error sa BLoC ay hinahawakan sa pamamagitan ng try-catch sa loob ng mapEventToState o on<Event>. Sa error, ang Bloc ay nagbabalik ng State ng error: yield LoadError(error.message). Sa UI, sinusuri ng BlocListener o BlocConsumer ang State para sa uri ng error at nagpapakita ng SnackBar o dialog. Ang BlocObserver ay pandaigdigang nagla-log ng lahat ng hindi nahahawakang exception.
BLoC — pattern na tiyak sa Flutter, dahil gumagamit ito ng Dart Stream at Flutter widgets. Ang konsepto ng Event → Bloc → State ay maaaring i-adapt para sa AngularDart at Server-side Dart, ngunit ang pangunahing ecosystem (BlocProvider, BlocBuilder, BlocObserver) ay nakatali sa Flutter. Para sa React Native gamitin ang Redux o MobX, para sa SwiftUI — Combine + MVVM.
Cubit — para sa mga simpleng state (counter, toggle, form na may 2-3 field). Bloc — para sa komplikadong logic (news feed, pag-checkout ng order, authentication). Pangunahing patakaran: kung kailangan ang pagsubaybay ng bawat aksyon (Event) para sa analytics o debugging — Bloc. Kung sapat na ang mga method na nagbabago ng state — Cubit. Ang parehong pattern ay nabubuhay nang magkasama sa iisang proyekto.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din