BLoC (Business Logic Component) — pola manajemen state untuk Flutter, diperkenalkan oleh Google pada tahun 2018 di DartConf. BLoC memisahkan logika bisnis dari antarmuka pengguna melalui aliran reaktif (Stream): UI mengirim Event, BLoC memprosesnya dan mengembalikan State baru melalui Stream. Menurut data pub.dev, paket flutter_bloc telah mengumpulkan lebih dari 11 ribu suka dan digunakan di ribuan aplikasi Flutter.
Poin Utama
BLoC (Business Logic Component) — pola arsitektur untuk Flutter di mana logika bisnis ditempatkan di kelas terpisah, terisolasi dari UI. BLoC menerima data masukan melalui aliran peristiwa (Event) dan menghasilkan data keluaran melalui aliran state (State). Lapisan presentasi (Widget) hanya berlangganan aliran State dan menampilkan UI, tanpa pernah menjalankan logika bisnis secara langsung.
Konsep BLoC didasarkan pada pemrograman reaktif dan pola Observer. Setiap komponen BLoC adalah modul terpisah dengan kontrak yang jelas: kumpulan Event (apa yang bisa terjadi) dan kumpulan State (apa yang bisa ditampilkan) diketahui. Pengembang tidak dapat mengubah state "secara tidak sengaja" dari UI — hanya melalui Event tertentu. Ini membuat kode dapat diprediksi dan diuji.
Menurut survei Flutter Community 2025, BLoC menempati posisi kedua dalam popularitas di antara solusi manajemen state di Flutter setelah Provider. Keunggulan utama: tipifikasi ketat, isolasi logika, dukungan Stream bawaan, ekosistem utilitas yang kaya (BlocProvider, BlocListener, BlocSelector).
Arsitektur BLoC dibangun di sekitar tiga entitas: Event (masukan), Bloc (pemroses), dan State (keluaran). Widget mengirim Event melalui metode add(). Bloc menerima Event dalam metode mapEventToState atau on<Event>, menjalankan logika bisnis dan menghasilkan State baru melalui yield. Widget menerima State melalui Stream dan menggambar ulang.
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;
}
}
}Keamanan tipe: Bloc diparametrikan dengan dua tipe — Event dan State. Kompiler Dart memeriksa bahwa Widget hanya memanggil Event yang dideklarasikan, dan Bloc hanya mengembalikan State yang dideklarasikan. Kesalahan runtime seperti "Tindakan Tidak Dikenal" dikecualikan.
Close dan Dispose: Bloc mengimplementasikan antarmuka Closeable. Saat widget dihancurkan, Bloc secara otomatis menutup Stream melalui metode close(). Kebocoran langganan reaktif tidak mungkin terjadi — BlocProvider mengelola siklus hidup Bloc, menghubungkannya dengan rute atau halaman.
Cubit — implementasi sederhana Bloc tanpa Event, diperkenalkan dalam paket flutter_bloc 6.0. Cubit mendeklarasikan metode langsung alih-alih kelas Event: increment(), fetchData(). Secara internal, Cubit menggunakan mekanisme berbasis Stream yang sama, tetapi menyembunyikan lapisan Event. Ini mengurangi boilerplate hingga 40-50% untuk skenario sederhana.
| Karakteristik | Bloc | Cubit |
|---|---|---|
| Kelas Event | Wajib | Tidak diperlukan |
| Boilerplate | Tinggi | Rendah |
| Pelacakan Tindakan | Melalui tipe Event | Hanya nama metode |
| Cocok untuk | Skenario kompleks | State sederhana |
| Analitik | Otomatis melalui Event | Manual |
Kapan memilih Cubit: state dengan 2-3 varian (loading, loaded, error), formulir sederhana, penghitung, state UI (terbuka/tertutup). Kapan Bloc: logika bisnis kompleks dengan banyak tindakan: checkout pesanan, otentikasi, sinkronisasi data. Bloc memberikan pelacakan detail setiap tindakan melalui Event — setiap panggilan dicatat di BlocObserver.
BlocObserver — pengamat global yang melacak semua Bloc dan Cubit dalam aplikasi. Memungkinkan pencatatan Event, State, kesalahan, dan transisi. Cukup menghubungkan satu instance: Bloc.observer = AppBlocObserver(), dan seluruh pelacakan state aplikasi tersedia secara terpusat.
BlocProvider — InheritedWidget dari flutter_bloc yang menyediakan Bloc ke widget anak. Saat inisialisasi widget, BlocProvider membuat Bloc, dan saat dihancurkan — secara otomatis menutupnya melalui close(). BlocProvider dapat ditempatkan di tingkat MaterialApp (Bloc global) atau di tingkat rute tertentu (Bloc lokal).
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 yang membangun ulang UI pada setiap State baru. BlocListener — untuk efek samping (memproses State sekali tanpa membangun ulang UI): menampilkan SnackBar, navigasi ke layar lain. BlocConsumer — kombinasi Builder dan Listener untuk kasus di mana diperlukan pembangunan ulang dan efek samping. BlocSelector — untuk pembangunan ulang selektif hanya saat perubahan bidang State tertentu.
MultiBlocProvider — widget untuk BlocProvider bersarang tanpa meningkatkan tingkat sarang. Aplikasi Flutter dengan 10-15 Bloc menggunakan MultiBlocProvider di tingkat root untuk mendaftarkan semua Bloc yang tersedia di seluruh aplikasi: AuthenticationBloc, CartBloc, SettingsBloc.
BLoC diuji secara terisolasi tanpa widget Flutter. Cukup mengimpor paket Dart flutter_test dan paket bloc_test. Skenario pengujian: membuat Bloc, menambahkan Event, memeriksa State. blocTest — utilitas yang mengotomatiskan urutan: build → act → expect.
blocTest<CounterBloc, int>(
'emits [1] when Increment is added',
build: () => CounterBloc(),
act: (bloc) => bloc.add(Increment()),
expect: () => [1],
)Mocking: BLoC yang bergantung pada repositori atau API diuji dengan mock melalui mocktail. Repositori di-mock pada tingkat abstraksi, Bloc menerima dependensi yang di-mock melalui konstruktor. Hydrated Bloc — ekstensi untuk menyimpan/memulihkan state secara otomatis di penyimpanan lokal. Diuji dengan HydratedBlocStorage dan penyimpanan file sementara.
Folder dan file: struktur khas proyek Flutter dengan BLoC: bloc/counter_bloc.dart, bloc/counter_event.dart, bloc/counter_state.dart. Untuk 30+ layar, pengelompokan berdasarkan fitur direkomendasikan: features/auth/bloc/, features/cart/bloc/. Setiap Bloc — file terpisah, setiap Event dan State — baik di file terpisah, atau dalam satu file dengan Bloc.
Kinerja: BLoC tidak menciptakan overhead pada Stream kosong. BlocBuilder menggunakan buildWhen untuk memfilter pembangunan ulang — widget hanya diperbarui saat kondisi tertentu berubah. Close menjamin bahwa Bloc yang tidak aktif tidak mengonsumsi memori. Menurut Flutter DevTools, BLoC menambahkan kurang dari 1% ke ukuran bundel.
Migrasi dari Provider: BLoC mudah hidup berdampingan dengan Provider dalam proyek yang sama. Migrasi bertahap: pertama Provider yang paling kompleks diganti dengan Bloc, kemudian sisanya. BlocProvider kompatibel dengan pohon Provider: widget lama dapat menggunakan Provider, yang baru — BlocProvider, dalam aplikasi yang sama.
Pertanyaan yang Sering Diajukan
BLoC menggunakan Event + Stream untuk isolasi logika bisnis dan tipifikasi ketat. Provider — pembungkus di atas InheritedWidget untuk injeksi dependensi sederhana dan ChangeNotifier. BLoC lebih cocok untuk skenario kompleks dengan banyak state, Provider — untuk state UI lokal. BLoC membutuhkan lebih banyak boilerplate, tetapi memberikan pelacakan penuh melalui Event.
Hydrated Bloc — ekstensi dari paket hydrated_bloc yang secara otomatis menyimpan State terakhir di penyimpanan lokal (secara default Hive). Saat aplikasi dimulai ulang, Bloc mengembalikan state yang disimpan alih-alih state awal. Ini memecahkan masalah persistensi tanpa panggilan penyimpanan manual: login, keranjang, pengaturan disimpan secara otomatis antar sesi.
Kesalahan di BLoC ditangani melalui try-catch di dalam mapEventToState atau on<Event>. Saat terjadi kesalahan, Bloc mengembalikan State error: yield LoadError(error.message). Di UI, BlocListener atau BlocConsumer memeriksa State untuk tipe kesalahan dan menampilkan SnackBar atau dialog. BlocObserver secara global mencatat semua pengecualian yang tidak tertangani.
BLoC — pola khusus Flutter, karena menggunakan Dart Stream dan widget Flutter. Konsep Event → Bloc → State dapat diadaptasi untuk AngularDart dan Server-side Dart, tetapi ekosistem utama (BlocProvider, BlocBuilder, BlocObserver) terikat pada Flutter. Untuk React Native gunakan Redux atau MobX, untuk SwiftUI — Combine + MVVM.
Cubit — untuk state sederhana (penghitung, toggle, formulir dengan 2-3 bidang). Bloc — untuk logika kompleks (feed berita, checkout pesanan, otentikasi). Aturan utama: jika pelacakan setiap tindakan (Event) diperlukan untuk analitik atau debugging — Bloc. Jika metode yang mengubah state sudah cukup — Cubit. Kedua pola hidup berdampingan dalam proyek yang sama.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga