In Flutter applications, the Flutter BLoC (Business Logic Component) is used to manage the state. It helps separate business logic from UI. It ensures that the user interface is not strongly liaison with the business logic, making the app more versatile. It is powerful since it allows the creation of all kinds of applications. For instance, the Flutter bloc is appropriate in both production and learning environments.
Key Concepts of BLoC
- Streams: Streams help in managing user actions and data, and how it flows through your app. In simple words, streams are like rivers that carry messages(messages can be anything, such as user actions or data updates).
- Sink: It's where you input data that you want to process. Data is poured into the sink, which then travels through it. A sink is like a place where you pour water into a stream.
- Stream Controller: A Stream Controller helps manage the streams, sinks and data, ensuring that data flows correctly through the system. In other words, it is a controller that controls the flow of water in the streams.
- Stream Builder: It updates the UI on the based of latest data in the stream. It updates the part of the app it's watching whenever new data comes down the stream through the sink. It's like a watchman that keeps an eye on the stream.
Installation of Flutter BLoC package
Step 1: Create a new Flutter Application
Create a new Flutter application using the command Prompt. To create a new app, write the following command and run it.
flutter create app_name
To know more about it refer this article: Creating a Simple Application in Flutter
Step 2: Add Dependencies
To add the dependency to the pubspec.yaml file, add flutter_bloc as a dependency in the dependencies part of the pubspec.yaml file, as shown below:
pubspec.yaml
dependencies:
flutter:
sdk: flutter
flutter_bloc: ^8.1.6
cupertino_icons: ^1.0.6
Now, run the below command in the terminal.
flutter pub get
Or
Run the below command in the terminal.
flutter pub add flutter_bloc
Import the BLoC Package in the Dart Code
To use the BLoC in your Flutter application, follow the given steps.
Step 1: Install the Bloc Extension
Install the following bloc extension in VSCode.
Note: If You are not using Vs Code or Don't want to automate the folder structure then, Skip this step and do it manually by creating every file.
It will helps you to generate the boilerplate code and folder structure automatically, for that follow the steps to below.
- Create a folder
After installing the VSCode extension, create a new folder inside the lib folder and name it Home.
- Select New Bloc
Now, Right click on Home folder, it will display a option named 'Bloc: New Bloc' select that option.
- Enter Bloc Name
After selecting New Bloc, it will ask for the name of the Bloc. Enter the New Bloc name as 'Home' and click on Enter!.
Then, it will create a new folder in your Home folder named bloc with all required files as image below.
Step 2: Working with home_event.dart.
Note: If you are not following step1 create a folder structure manually as the image located above the Step 2.
Here we only have one event, CounterIncrementPressed to code, and that contains a parameter count because we need to pass the previous state before updating the state.
home_event.dart:
home_event.dart
part of 'home_bloc.dart';
/// Base class for all events related to the Home feature.
/// This class is immutable and sealed, meaning no other classes
/// can extend it outside of this file.
@immutable
sealed class HomeEvent {}
/// Event triggered when the counter increment button is pressed.
/// This extends the base `HomeEvent` class.
class CounterIncrementPressed extends HomeEvent {
final int counter;
CounterIncrementPressed({required this.counter});
}
Step 3: Working with home_state.dart
Here, also we only have one state to code and it also have one parameter counter because it is used to update state and emit to UI.
home_state.dart
part of 'home_bloc.dart';
/// Base class for all states in the Home feature.
/// This class is immutable and sealed, meaning no other classes
/// outside this file can extend it.
@immutable
sealed class HomeState {}
/// Initial state of the Home feature.
/// Represents the default state when no specific state is set.
final class HomeInitial extends HomeState {}
/// State representing the counter value.
/// Extends [HomeInitial] and holds the current counter value.
final class CounterState extends HomeInitial {
/// The current value of the counter.
final int counter;
/// Constructor for [CounterState].
/// Requires the [counter] value to be provided.
CounterState({required this.counter});
}
Step 4: Working with home_bloc.dart
This class (HomeBloc) catches the triggered event (CounterIncrementPressed) with some previous state (event parameter in CounterIncrementPressed ) and updates it and emits through the state (CounterState(counter: event.counter + 1)) to UI.
home_bloc.dart:
home_bloc.dart
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
// Importing the parts for event and state definitions
part 'home_event.dart';
part 'home_state.dart';
// The HomeBloc class extends Bloc and manages the state of the application
class HomeBloc extends Bloc<HomeEvent, CounterState> {
// Constructor initializes the bloc with an initial state
HomeBloc() : super(CounterState( counter: 0)) {
// Specific event handler for CounterIncrementPressed
on<CounterIncrementPressed>((event, emit) {
// Emits a new CounterState with the incremented counter value
emit(CounterState(counter: event.counter + 1));
});
}
}
Step 5: Working with UI
We develop a simple counter app UI with a FloatingActionButton and Text widget wrapped with Center to display the count.
-BlocProvider: Wrap the home class CounterPage() with BlocProvider, it is used initialize the state i.e, here the counter value '0' in home_bloc.dart.
Dart
// Providing the HomeBloc to the widget tree
home: BlocProvider(
create: (context) => HomeBloc(),
child: CounterPage(),
),
- Initialize the instance: Used to access events in home_event.dart to perform the trigger.
Dart
// Accessing the HomeBloc instance from the context
final HomeBloc counterBloc = BlocProvider.of<HomeBloc>(context);
- BlocBuilder: Wrap the Scaffold with BlocBuilder that contains builder as a parameter with (context, state), and here 'state' is used to get the updated state to UI throw "." operation, for example (state.count).
Dart
BlocBuilder<HomeBloc, CounterState>(
// Rebuilding the UI based on the current state of HomeBloc
builder: (context, state) {
return Scaffold(
body: Center(
// Displaying the current counter value
child: Text('Counter: ${state.counter}',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blue.shade800,
foregroundColor: Colors.white,
onPressed: () {
// Dispatching an event to increment the counter
counterBloc.add(CounterIncrementPressed(counter: state.counter));
},
child: Icon(Icons.add),
),
);
},
);
Full UI Code
main.dart:
main.dart
// lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_geeks/Home/bloc/home_bloc.dart';
void main() {
// Entry point of the Flutter application
runApp(MyApp());
}
// Root widget of the application
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
// Providing the HomeBloc to the widget tree
home: BlocProvider(
create: (context) => HomeBloc(),
child: CounterPage(),
),
);
}
}
// Widget representing the Counter Page
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Accessing the HomeBloc instance from the context
final HomeBloc counterBloc = BlocProvider.of<HomeBloc>(context);
return BlocBuilder<HomeBloc, CounterState>(
// Rebuilding the UI based on the current state of HomeBloc
builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter BLoC Example'),
backgroundColor: Colors.blue.shade800,
foregroundColor: Colors.white,
),
body: Center(
// Displaying the current counter value
child: Text('Counter: ${state.counter}',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blue.shade800,
foregroundColor: Colors.white,
onPressed: () {
// Dispatching an event to increment the counter
counterBloc.add(CounterIncrementPressed(counter: state.counter));
},
child: Icon(Icons.add),
),
);
},
);
}
}
Program Flow:
When the App started with the help of BlocProvider, the counter value was '0'.
BlocProvider(
create: (context) => HomeBloc(),
.....
)
As we are calling HomeBloc() class in home_bloc.dart and that calling CounterState( counter: 0) with '0' as counter value as below:
HomeBloc() : super(CounterState( counter: 0)) {
...
}
When it come to UI after that, BlocBuilder catching that state i.e, counter value '0' and it will display Zero at starting of the app.
BlocBuilder<HomeBloc, CounterState>(
// Rebuilding the UI based on the current state of HomeBloc
builder: (context, state) {
return Scaffold(
....
body: Text('Counter: ${state.counter}',
.....
When the user taps on the FloatingActionButton, it triggers the event.
FloatingActionButton(
onPressed: () {
// Dispatching an event to increment the counter
counterBloc.add(CounterIncrementPressed(counter: state.counter));
},
child: Icon(Icons.add),
),
Then it is taking current counter value and going to home_bloc.dart and searches for right on catch(on<CounterIncrementPressed>), if it finds then it will emit the state like CounterState(counter: event.counter +1 ), here with the event parameter we can easily access the previous state(event.counter) i.e, counter value and it implicitly updating the counter value and after that it is emitting that to UI.
on<CounterIncrementPressed>((event, emit) {
emit(CounterState(counter: event.counter + 1));
});
Then, BlocBuilder in the main.dart catching that updated state and displaying it in the UI.
BlocBuilder<HomeBloc, CounterState>(
// Rebuilding the UI based on the current state of HomeBloc
builder: (context, state) {
return Scaffold(
....
body: Text('Counter: ${state.counter}',
.....
This is what is happening in the whole code.
Complete Source Code
home_event.dart
part of 'home_bloc.dart';
/// Base class for all events related to the Home feature.
/// This class is immutable and sealed, meaning no other classes
/// can extend it outside of this file.
@immutable
sealed class HomeEvent {}
/// Event triggered when the counter increment button is pressed.
/// This extends the base `HomeEvent` class.
class CounterIncrementPressed extends HomeEvent {
final int counter;
CounterIncrementPressed({required this.counter});
}
home_state.dart
part of 'home_bloc.dart';
/// Base class for all states in the Home feature.
/// This class is immutable and sealed, meaning no other classes
/// outside this file can extend it.
@immutable
sealed class HomeState {}
/// Initial state of the Home feature.
/// Represents the default state when no specific state is set.
final class HomeInitial extends HomeState {}
/// State representing the counter value.
/// Extends [HomeInitial] and holds the current counter value.
final class CounterState extends HomeInitial {
/// The current value of the counter.
final int counter;
/// Constructor for [CounterState].
/// Requires the [counter] value to be provided.
CounterState({required this.counter});
}
home_bloc.dart
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
// Importing the parts for event and state definitions
part 'home_event.dart';
part 'home_state.dart';
// The HomeBloc class extends Bloc and manages the state of the application
class HomeBloc extends Bloc<HomeEvent, CounterState> {
// Constructor initializes the bloc with an initial state
HomeBloc() : super(CounterState( counter: 0)) {
// Specific event handler for CounterIncrementPressed
on<CounterIncrementPressed>((event, emit) {
// Emits a new CounterState with the incremented counter value
emit(CounterState(counter: event.counter + 1));
});
}
}
main.dart
// lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_geeks/Home/bloc/home_bloc.dart';
void main() {
// Entry point of the Flutter application
runApp(MyApp());
}
// Root widget of the application
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
// Providing the HomeBloc to the widget tree
home: BlocProvider(
create: (context) => HomeBloc(),
child: CounterPage(),
),
);
}
}
// Widget representing the Counter Page
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Accessing the HomeBloc instance from the context
final HomeBloc counterBloc = BlocProvider.of<HomeBloc>(context);
return BlocBuilder<HomeBloc, CounterState>(
// Rebuilding the UI based on the current state of HomeBloc
builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter BLoC Example'),
backgroundColor: Colors.blue.shade800,
foregroundColor: Colors.white,
),
body: Center(
// Displaying the current counter value
child: Text('Counter: ${state.counter}',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blue.shade800,
foregroundColor: Colors.white,
onPressed: () {
// Dispatching an event to increment the counter
counterBloc.add(CounterIncrementPressed(counter: state.counter));
},
child: Icon(Icons.add),
),
);
},
);
}
}
Output:
Similar Reads
Flutter Bloc - Basic Search
In this article, we are going to develop a Basic Search App using Flutter Bloc and Clean Architecture. In Flutter applications, the Flutter BLoC (Business Logic Component) is used to manage the state. It helps separate business logic from UI. It ensures that the user interface is not strongly liaiso
15+ min read
Flutter - Popover Button
In Flutter, Popover buttons are a user interface pattern commonly used to display additional content or actions in response to user input. They are particularly useful when you want to present contextual options by blurring the main screen. The Popover package in Flutter simplifies the implementatio
8 min read
Flutter - RFlutter Alerts
In Flutter, rflutter_alert is useful to create alerts in applications easily. It is a customizable and best way to create alerts in Flutter. In this article, we will see the different styles of alerts we can create with this awesome Flutter library. Follow the article to learn about it. Adding the d
4 min read
Flutter vs Flutter 2
Overview :In this article, we will study the difference between Flutter 1 and Flutter 2. Flutter 1 was launched by Google in 2017. The reason behind launching this was so that the developer could use only a single code to develop applications for multiple platforms like Android, iOS, Linux, macOS. H
4 min read
Flutter - PhotoHero Class
In Flutter, a Hero Widget is used to create a hero animation. A hero in this context refers to a widget that moves in between screens. This is one of the most fundamental types of animation used in the application, especially if the app deals with media like images. Simply put, a hero animation is w
3 min read
Flutter - Gradient Button
Buttons are the building block of any Android Application, Buttons are helping in to perform specific tasks like Navigating from one screen to another screen, Showing the Toast, Sign-in, Sign-up buttons, and many more. But giving the effects of the colors to the Button makes the Button more pretty.
3 min read
Placeholder Flutter
Placeholder is a popular, inbuilt widget of the Flutter framework which creates an empty canvas/container on the screen to put content into, just like its name implies. It is analogous to both the placeholder attribute and the <div> tag of HTML. Almost all Flutter developers have reported usin
3 min read
FlipCard in Flutter
flip_card is a component that provides a flip card animation. It could be used for hiding and showing details of a product. A sample video is given below to get an idea about what we are going to do in this article. [video mp4="https://media.geeksforgeeks.org/wp-content/uploads/20220327094130/1.mp4"
3 min read
Flutter - Selectable Box
A selectable box is a box that can be selected with on click. If you are creating a list of boxes, And want these boxes can selectable. Then you can use the Selectable box widget. A sample video is given below to get an idea about what we are going to do in this article. How to use it? Just you have
3 min read
Flutter - File Structure
Flutter continues to be a top choice for cross-platform development in 2025. Be it a student's college project, a small startup, a unicorn, or big tech giants, all are using Flutter. The file structure is the organization of the data of an application. The file structure is something that plays a ve
6 min read