If you're new to Flutter state management, Bloc is one of the most powerful and scalable approaches. In this guide, you'll learn how to install and set up Bloc step by step with a simple working example.
How Bloc Works (Quick Overview)
Bloc separates your UI from business logic. The UI sends events, the Bloc processes them and produces states, and the UI reacts to those states. This makes your code predictable and testable.
What You'll Need
Before installing the BLoC package, make sure you have a Flutter project created. You can create one using flutter create my_app. Then open the project in your favourite editor.
Step 1: Add Dependencies
Open your pubspec.yaml file and add the following dependencies:
Then run flutter pub get in your terminal to fetch the packages.
Step 2: Create Your First Bloc
Create a folder structure like this to keep your code organised:
Step 3: Provide the Bloc
Wrap your widget tree with BlocProvider to make the bloc available. Usually this is done in main.dart or in a dedicated App widget.
Step 4: Use the Bloc in the UI
In your HomePage, use BlocBuilder to rebuild when the state changes, and context.read<CounterBloc>() to add events.
Optional: Add Bloc Observer for Logging
You can enable logging of all bloc events and states by creating a simple observer and setting it in main.dart.
Bloc vs Cubit
Cubit is a simpler version of Bloc that doesn't use events. You call methods directly on the Cubit to emit states. Use Cubit for simple state management and Bloc for complex flows with many event types.
Real-World Usage
The counter example is a starting point. Here’s how Bloc is used in real apps:
- Login form – validation, loading state, error messages
- API calls – fetch data with loading and error handling
- Shopping cart – add/remove items, calculate total
- Multi‑step forms – preserve state across screens
Common Mistakes
- ❌ Forgetting Equatable – states and events won't be compared correctly, causing unnecessary rebuilds.
- ❌ Emitting the same state instance – UI won’t update if the state object is identical.
- ❌ Creating Bloc inside
build– useBlocProviderorBlocProvider.valueto avoid recreation. - ❌ Using the wrong
BuildContext– ensure you have access to the correct provider. - ❌ Not handling loading/error states – users need feedback during async operations.
What's Next?
Now that you have a working Bloc setup, explore more advanced topics:
BlocConsumer– combine builder and listener in one widget.BlocProvider.value– share an existing bloc with a new subtree.- Testing – use
bloc_testto write unit tests for your blocs. - Architecture – see how to structure larger apps with Bloc.
Next, learn how Bloc architecture helps structure large applications.