State Management in Flutter
There are lots of “State Management” techniques in the Flutter ecosystem which can feel overwhelming. In getting started its best to learn one and build on it over time.
BLoC is a widely adopted state management solution in the Flutter ecosystem. When implementing BLoC, developers often face a choice in how to represent the different states of their application data.
A common introductory approach is to create a distinct class for every possible state. While this demonstrates the basic flow of events and states, it introduces limitations as an application scales. Specifically, transitioning between completely different state classes can cause the UI to lose previously loaded data, resulting in undesirable loading indicators or blank screens when fetching updates.
This guide outlines the recommended approach for structuring BLoC using the Single State pattern.
Core Architecture
Section titled “Core Architecture”BLoC (Business Logic Component) separates the UI layer from the business logic, promoting testability and predictability. The architecture follows a unidirectional data flow:
- Events: Represent user interactions or system triggers (e.g., a button tap).
- Logic: The BLoC processes incoming events and performs necessary operations like API calls or database queries.
- States: The BLoC emits new states, which the UI listens to in order to rebuild dynamically.

Handling Multiple State Classes
Section titled “Handling Multiple State Classes”A common introductory pattern is defining separate classes for each state:
The limitation of this approach becomes apparent during data refreshes. If the
current state is UserSuccess and the user triggers a refresh, the BLoC
transitions to UserLoading. Because UserLoading does not contain the
profile data, the UI loses access to the previously loaded information. This
typically results in the screen clearing entirely to show a loading spinner,
creating a jarring user experience.
Recommended Approach: The Single State Pattern
Section titled “Recommended Approach: The Single State Pattern”To maintain context during state transitions, it is recommended to use a single
state class combined with a status enum and a copyWith method. This allows the
application to indicate loading or error states without discarding previously
fetched data.
1. The Status Enum
Section titled “1. The Status Enum”Define the possible statuses for the data fetching lifecycle:
2. The Single State Class
Section titled “2. The Single State Class”By leveraging the Equatable package, the BLoC can perform value-based
comparisons to ensure the UI only rebuilds when the state has actually changed.
3. The Events
Section titled “3. The Events”Events should represent actions that have occurred rather than commands indicating what the BLoC should do.
Implementing the BLoC
Section titled “Implementing the BLoC”The BLoC maps incoming events to state emissions. When a refresh event occurs,
the BLoC updates the status to loading using copyWith, preserving the
existing profile data.
UI Integration
Section titled “UI Integration”Using the single state pattern simplifies the UI implementation. The application can display error messages or loading indicators without removing the existing content from the screen.