Flutter BLoC is a popular state management library for developing reactive applications. It is built on top of the RxDart package and provides a simple way to manage application state and trigger UI updates in response to changes in that state.
The core concepts of Flutter Bloc include:
BlocBuilder
widget to listen for state changes.Let's build a simple counter app to demonstrate how to use Flutter BLoC. We'll have two buttons, one to increment the counter and another to decrement it. The updated count will be displayed on the screen in real-time.
First, we'll create a new Flutter project.
flutter create counter_app
cd counter_app
Now let's add the dependencies for rxdart
and bloc
.
dependencies:
flutter:
sdk: flutter
rxdart: "^0.25.0"
bloc: "^7.0.0"
Next, let's create the CounterEvent
and CounterState
classes.
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}
class DecrementEvent extends CounterEvent {}
abstract class CounterState {}
class InitialCounterState extends CounterState {
final int count;
InitialCounterState(this.count);
}
class UpdatedCounterState extends CounterState {
final int count;
UpdatedCounterState(this.count) : super();
}
Our InitialCounterState
will represent the initial state of the counter app with a count of zero. The UpdatedCounterState
will represent the state after the count has been incremented or decremented.
Now let's create the CounterBloc
itself.
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc() : super(InitialCounterState(0));
@override
Stream<CounterState> mapEventToState(CounterEvent event) async* {
if (event is IncrementEvent) {
yield UpdatedCounterState(state.count + 1);
} else if (event is DecrementEvent) {
yield UpdatedCounterState(state.count - 1);
}
}
}
The CounterBloc
extends the Bloc
class and provides the implementation for the mapEventToState
method. This is where we handle incoming events and map them to new states. We have two event types in this example, one for incrementing the count and one for decrementing it. When an event is received, a new UpdatedCounterState
is emitted with the updated count value.
Last of all, let's create the UI of our application using the BlocBuilder
widget, which listens for updates to the state of our CounterBloc
and rebuilds the UI accordingly.
class CounterApp extends StatelessWidget {
final CounterBloc _counterBloc = CounterBloc();
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Counter App'),
),
body: BlocBuilder<CounterBloc, CounterState>(
bloc: _counterBloc,
builder: (BuildContext context, CounterState state) {
if (state is UpdatedCounterState) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Count:',
style: TextStyle(fontSize: 20),
),
Text(
state.count.toString(),
style: TextStyle(fontSize: 50),
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FloatingActionButton(
onPressed: () {
_counterBloc.add(DecrementEvent());
},
child: Icon(Icons.remove)),
SizedBox(width: 20),
FloatingActionButton(
onPressed: () {
_counterBloc.add(IncrementEvent());
},
child: Icon(Icons.add)),
],
)
],
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
),
);
}
}
The UI that we create is a simple column of widgets that includes the current count, two buttons to increment and decrement the count, and a loading spinner for initial state. To update the count, we add the corresponding CounterEvent
to the CounterBloc
using the add()
method. The BlocBuilder
widget handles the rest, listening for state changes and updating the UI accordingly.
Flutter BLoC is a powerful technique for managing state in your Flutter applications. By following the core concepts and example above, you'll be well on your way to building scalable, reactive applications.