BLoC with typed events and states in Flutter: solved exercise
BLoC with typed events and states in Flutter: solved exercise
The BLoC (Business Logic Component) pattern separates business logic from the UI through a unidirectional flow: the UI dispatches events, the BLoC processes them and emits new states. This makes code testable and predictable.
Problem statement
Build a screen that loads a list of posts from a simulated remote source. It must handle three distinct states: loading, loaded, and error. The user can refresh the list with a button.
Dependencies
Flutter solution
Expected result
- On app open, a
CircularProgressIndicatorappears. - After 1 second, a list of 5 posts is rendered.
- The refresh button shows the loader again and reloads.
- Uncommenting the
throwshows the error screen with a retry button.
Common mistakes
- Registering the same event type twice with
on<>: the second handler is never called; consolidate the logic into one. - Emitting outside the handler in a nested async callback: always use
emitdirectly inside the handler or via theEmitter. - Mutable state objects: never modify a list in place; always emit a new state with a new list instance.
Cubit vs BLoC here
With Cubit you would call postsBloc.load() from the UI. With BLoC the UI only dispatches PostsLoadRequested() and knows nothing about how it is resolved, which enables:
- Testing the BLoC in isolation without touching the UI.
- Adding logging or analytics per event without modifying the UI.
- Transforming or debouncing events before processing them.
Practical use
This pattern is the standard in large teams and apps with complex data flows: feeds, search with filters, shopping carts, real-time notifications.
Recommended next exercise
- Unit test of repository in Flutter: solved exercise
- Layered architecture in Flutter: solved exercise
- Dependency injection with get_it in Flutter: solved exercise
- All Flutter exercises
Guided practice and next step
- More Flutter exercises
- C exercises to strengthen fundamentals
- Programming in C in 100 Solved Exercises
- View the book on Amazon (included in Kindle Unlimited)
- Subscribe to the newsletter
FAQ
Why use sealed for events and states?
With sealed, the Dart compiler guarantees that the switch is exhaustive: if you add a new event or state without updating the switch, the compiler warns you at compile time.
When to use BlocListener instead of BlocBuilder?
BlocListener is for side effects (showing a snackbar, navigating, playing a sound) that should happen once, not for rebuilding the UI.
Can BlocBuilder and BlocListener be combined?
Yes, with BlocConsumer, which merges both in a single widget when you need to react to state changes both in the UI and via side effects.