BLoC — ano ito, Business Logic Component sa Flutter

May-akda: IT Sectr Nai-publish: 2026-02-19 Oras ng pagbabasa: 7 min

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

  • Event — input signal na naglalarawan ng aksyon: pagpindot ng button, pag-load ng datos
  • State — output state ng UI: datos na-load, error, naglo-load
  • Bloc — pangunahing klase na tumatanggap ng Event at nagbabalik ng State sa pamamagitan ng Stream
  • Cubit — pinasimpleng bersyon ng Bloc na walang Event, direktang tumatawag ng mga function
  • BlocProvider — Flutter widget para sa pag-inject ng Bloc sa widget tree

Ano ang BLoC?

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: Event → Bloc → State

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.

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;
    }
  }
}

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.

Bloc at Cubit: paghahambing

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.

KatangianBlocCubit
Mga Event classKailanganHindi kailangan
BoilerplateMataasMababa
Pagsubaybay ng aksyonSa pamamagitan ng Event typePangalan lang ng method
Angkop para saMga komplikadong senaryoMga simpleng state
AnalyticsAwtomatiko sa pamamagitan ng EventManual

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 at BlocBuilder

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).

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 — 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.

Pagsubok ng BLoC

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.

Dart
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.

BLoC sa produksyon

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

Ano ang pagkakaiba ng BLoC sa Provider sa Flutter?

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.

Ano ang Hydrated Bloc?

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.

Paano hawakan ang mga error sa BLoC?

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.

Maaari bang gamitin ang BLoC sa ibang frameworks?

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.

Ano ang pipiliin: Bloc o Cubit?

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

  • BLoC — pattern ng pamamahala ng state ng Flutter sa pamamagitan ng Event → Stream → State
  • Event — aksyon (click, load), State — reaksyon (datos, error, naglo-load)
  • Cubit — pinasimpleng bersyon na walang Event, hanggang 50% mas kaunting boilerplate
  • BlocProvider — pag-inject ng Bloc sa widget tree na may awtomatikong close
  • BlocObserver — pandaigdigang pagsubaybay ng lahat ng Bloc at Cubit sa application
  • Hydrated Bloc — awtomatikong persistency ng state sa pamamagitan ng Hive
  • blocTest — utility para sa modular testing ng Bloc na may isolation mula sa Flutter

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.

Pag-usapan ang proyekto

Basahin din