What is the BLoC pattern in Flutter?
Short Answer
BLoC (Business Logic Component) separates UI from business logic by having the UI dispatch Events into a Bloc, which processes them and emits new States that the UI rebuilds from — all communication happens through a strict, unidirectional stream of Events and States.
A widget never mutates state directly. Instead, it sends an Event (e.g. `IncrementPressed()`) into a Bloc using `context.read<CounterBloc>().add(IncrementPressed())`. The Bloc's internal logic maps that event to a new State (e.g. `CounterState(count: count + 1)`) and emits it. The UI listens via `BlocBuilder` (rebuild on state changes) or `BlocListener` (side effects like navigation/snackbars without rebuilding), so the data flow is always Event → Bloc → State → UI, never the reverse.
This strict separation makes business logic fully testable without any widget tree at all — you can unit test a Bloc by feeding it events and asserting on the emitted states, with no Flutter dependency in the test.
Common Mistakes
- ×Putting Flutter-specific code (like `BuildContext`) inside a Bloc — it should be pure Dart, completely UI-agnostic.
- ×Confusing `BlocBuilder` (for rebuilding UI) with `BlocListener` (for one-off side effects) and using the wrong one.
Related Questions
How does Riverpod differ from Provider?
Riverpod is a redesign by the same author as Provider that removes the dependency on BuildContext and the widget tree, catching errors at compile time instead of runtime, and making providers globally accessible and easily testable.
What is Clean Architecture and how does it apply to Flutter?
Clean Architecture separates an app into independent layers — typically presentation, domain, and data — where inner layers (business logic) never depend on outer layers (UI, frameworks, databases), so business rules can be tested and reused independently of Flutter itself.