The Bloc class is the core of the BLoC pattern. It manages a stream of states, reacts to events, and ensures predictable state transitions. This guide covers everything from basic usage to advanced patterns, helping you master the Bloc class in Flutter.
What is the Bloc Class?
Bloc<Event, State> is an abstract class that transforms a stream of incoming events into a stream of outgoing states. It provides a structured way to handle business logic, separate from the UI. Each bloc extends this class and defines how events are processed.
Bloc Constructor and Initial State
When extending Bloc, you must call super(initialState) to set the starting state. The constructor is also where you inject dependencies and register event handlers.
The on<Event> Method
Use on<Event> to register a handler for a specific event type. The handler receives the event and an Emitter that can be used to emit one or more states. You can also pass an optional transformer to control how events are processed.
Handlers can be synchronous or asynchronous. Use emit inside the handler to output states.
Emitting States
The Emitter<State> passed to handlers is used to emit states. You can call emit multiple times within a handler to produce a sequence of states (e.g., loading → success).
Bloc Lifecycle
The Bloc class provides lifecycle methods that you can override to perform setup and cleanup.
Called whenever a new state is emitted. Receives the Change<State> containing the previous and next states. Useful for logging or analytics.
Called when an uncaught exception occurs inside an event handler. Allows you to handle errors globally.
Called when the bloc is closed. Override to dispose of any resources (e.g., streams, controllers).
Adding Events
Events are added to the bloc using the add method. This can be done from anywhere that has access to the bloc instance.
You can also add events from within the bloc itself (e.g., after a successful operation, trigger another event).
Event Transformers
Transformers control the flow of events. You can use the bloc_concurrency package for common strategies: sequential (default), concurrent, droppable, and restartable. Custom transformers can be built using StreamTransformer.
Bloc vs Cubit
Cubit is a simplified version of Bloc that doesn't use events. Instead, it exposes methods that directly emit states. Use Cubit for simple state management; use Bloc when you need to leverage event streams, transformers, or complex event handling.
| Feature | Bloc | Cubit |
|---|---|---|
| Event-based | Yes | No |
| Event transformers | Yes | No |
| Emit methods | Via handlers | Directly on cubit |
| Traceability | High (events logged) | Lower |
| Complexity | Higher | Lower |
Testing the Bloc Class
Use bloc_test to test your bloc's behavior. You can verify that specific events produce expected states.
Best Practices
- Keep blocs focused – Each bloc should handle one feature or domain.
- Use dependency injection – Pass repositories and services via constructor for testability.
- Handle errors gracefully – Catch exceptions in handlers and emit error states.
- Avoid emitting unrelated states – Don't emit states that don't belong to the bloc's responsibility.
- Use
Equatablefor states and events – Prevents unnecessary rebuilds and simplifies equality. - Override
onErrorfor global error handling – Log errors or trigger fallback states. - Dispose blocs properly – Use
BlocProviderwhich automatically callsclose.
Common Mistakes
- ❌ Calling
emitafterclose– This will throw an error. Ensure you don't emit after bloc is closed. - ❌ Not handling exceptions – Uncaught exceptions stop the bloc; always catch and emit an error state.
- ❌ Creating blocs inside
build– UseBlocProviderto ensure proper lifecycle. - ❌ Mutating state objects – Always emit a new state object instead of modifying the existing one.
- ❌ Overusing global blocs – Provide blocs only where needed to avoid memory leaks.
What's Next?
Now that you understand the Bloc class, explore how to structure events effectively, or dive into testing and architecture patterns.
Next, learn about Bloc events and Bloc architecture.