Introduction
This article explains how state is managed in Flutter. There are methods used you may already know about, such as Provider, Inherited Widget, Scoped Model, Redux, etc. BLoC pattern is also a state management technique. BLoC pattern is somehow advanced compared to Scoped Model and it’s better in performance as well.
BLoC pattern uses the Sink and Stream concepts in which Sink accepts an input as event and Stream provides the output. BLoC pattern is a bit complicated in implementation from scratch but there is also a plugin that makes it easy. However, we are going to implement it from scratch to understand it before we jump to use the readymade plugin. Now, let’s see BLoC pattern implementation in Flutter in detail.
Implementing BLoC Pattern in Flutter
Step 1
The first and basic step is to create a new application in Flutter. If you are a beginner, you can check my blog Create a first app in Flutter. For now, I have created an app named as “flutter_bloc_pattern”.
Step 2
Now, you can see that you have a counter app by default and here, our purpose is to make the same app using the BLoC pattern. We are adding a decrement operation to it as well.
Step 3
Now, create a new file named counter_bloc_provider.dart. In this file, we will add an abstract class for events for increment and decrement operation which will be mapped in bloc pattern to handle the stream and sink controls.
We have state and event controller implementation in which when the constructor is generated, the event will be allocated to the state according to the event type. Following is the programming implementation of that.
- import 'dart:async';
- abstract class CounterEvent {}
- class IncrementEvent extends CounterEvent {}
- class DecrementEvent extends CounterEvent {}
- class CounterBloc {
- int _counter = 0;
- final _counterController = StreamController<int>();
- StreamSink<int> get _incrementCounter => _counterController.sink;
- Stream<int> get counter => _counterController.stream;
- final _counterEventController = StreamController<CounterEvent>();
- Sink<CounterEvent> get counterEventSink => _counterEventController.sink;
- CounterBloc() {
- _counterEventController.stream.listen(_mapEventToState);
- }
- void _mapEventToState(CounterEvent event) {
- if (event is IncrementEvent)
- _counter++;
- else
- _counter--;
- _incrementCounter.add(_counter);
- }
- void dispose(){
- _counterController.close();
- _counterEventController.close();
- }
- }
Step 4
Now, in the main.dart file, we will import bloc pattern class and define the stream for output and also, we will call an abstract event to add sink to increment and decrement counter variable. You will also see that the dispose() method is overridden because stream will consume memory which will be released when the widget is not in use. Following is the programming implementation of that.

Join the conversation! Your thoughts help the community grow.