What is BLoC?
BLoC is the abbreviation of the word Business Logic Components It aims to isolate the business logic of an application from its User Interface, making the application’s code simpler, flexible, adaptable, and capable of being tested.
- Developed by: Felix Angelov
- Sponsors: Very Good Ventures, Stream, Miquido
- Version: flutter_bloc: ^8.0.1(at the time of writing article)
Pros & Cons of BLoC Design Pattern
Before we move on to the Flutter Block tutorial Let’s look at some of the advantages and disadvantages of the block design pattern.
Pros of Using BLoC
Great documentation of various scenarios.
Separates the business logic from the UI which makes the code understandable.
It makes the product more tastier.
It is simple to track the states that an app has gone through.
Cons of Using BLoC
The learning curve is steep.
Not recommended for applications with simple requirements.
A little more boilerplate code, but it is easily handled with extensions.
Flutter BLoC Tutorial Goal
We will create a basic application to demonstrate how the BLoC utilizes streams to manage state and create a few tests for the block.
We will create a basic application to demonstrate how the BLoC utilizes streams to manage state and create a few tests for the block.
Initial Setup
Make sure to install the bloc extension in your editor; it will help create all boilerplate code and files required for the project(right-click on the lib folder, and it will give you the option for generation bloc for your project).
Make sure to match your pubspec.yaml file with mine to avoid any issues.
Want to have easy and hustle-free Flutter application development?
Neo Infoway is waiting for you! Contact us today to hire a Flutter developer to meet the requirements of your project with outstanding problem-solving abilities.
Understanding BLoC Concepts: Events and States
To understand the way that blocks work We must know what constitutes states and events.
events: These are the inputs that an app can receive (like pressing a button to load images, inputs for text, or any other inputs from users that our application might wish to get).
State: State is the state of the application, and can be altered according to an event that is received.
Bloc manages these states and events, i.e., it is able to take an entire flow of Events and convert them into streams of States as output.
Creating an Event
@immutable
abstract class AppBlocEvent {
const AppBlocEvent();
}
@immutable
class ChangeTextEvent extends AppBlocEvent {
const ChangeTextEvent();}
Moving forward to the Flutter Block Tutorial. We have made an event called ChangeTextEvent which will be fired whenever the button is pressed.
We use an abstraction of the AppBlocEvent Class since Bloc is expecting a single occasion to add to its stream. However, since there could be multiple events running in an app, we design an abstract class and then extend it when we need to add any new event and pass on multiple events to Bloc.
Creating a State
Event and State Management using BLoC Pattern
class AppBlocBloc extends Bloc {
final List textList = [
'Initial Text',
'Changed Text',
'Changed Again',
];
AppBlocBloc() : super(const AppState.empty()) {
on((event, emit) {
try {
int newIndex = state.index + 1;
if(newIndex >= textList.length) {
newIndex = 0;
}
emit(
AppState(
index: newIndex,
text: textList[newIndex],
),
);
} on Exception catch (e) {
// ignore: avoid_print
print(e);
}
});
}
}
Explanation
This is the section which contains the software.
When a it is added into the stream with clicking a button. It gets the event, i.e. the information you wish to share with the triggering events, you are able to access via this(like event.any_info which requires you to alter your event’s class to reflect this) emit is used to generate an event state specific to that event.
When a it is added into the stream with clicking a button. It gets the event, i.e. the information you wish to share with the triggering events, you are able to access via this(like event.any_info which requires you to alter your event’s class to reflect this) emit is used to generate an event state specific to that event.
state.index allows you to see the state that is currently in the application’s state.index. It lets you see the current state of the.
emit(AppState (…)): emit (…) is used to generate new states and triggers the rebuilding part of the built() build() function.
Connect the pieces.
At present the events, states, blocks and our application’s UI are not linked to each other in any manner. Let’s get them all connected.
Providing our BLoC
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:text_change/text_controller.dart';
import 'bloc/app_bloc_bloc.dart';
import 'bloc/app_bloc_state.dart';
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: BlocProvider(
create: (context) => AppBlocBloc(),
child: Scaffold(
appBar: AppBar(
title: const Text('Text Change'),
),
body: BlocConsumer(
listener: (context, state) {},
builder: (context, state) {
return Text Controller(
text: state.text,
);
},
),
),
),
);
}
}
Explanation: App.dart
BlocProvider (…): We use it to display an instance of our block by placing it under the base of the application to make it accessible to all users.
Create: It creates the version of our AppBloBloc.
BlocConsumer (…): It is the place in which everything takes place.
builder: ‘s responsible for creating it’s UI which is then rebuilt with every state changes. blocConsumer also includes listenWhen and buildWhen that, like the name suggests, can be customized to respond to specific state changes.
Triggering the Event and States
class TextChangeController extends StatelessWidget {
final String text;
const TextChangeController({Key? key, required this.text}) : super(key: key);
@override
Widget build (BuildContext context) {
return Column
children: [
TextChange(
text: text,
), // TextChange
ElevatedButton(
onPressed: () =>
context.read().add(const ChangeTextEvent()),
child: const Text('Change Text'),
), // ElevatedButton
), // [ ]
); // Column
)
)
In this case, we’ve included the event called ChangetTextEventonto an event’s stream which triggers a state change that triggers the rebuilding of BlocConsumer’s builder() inside BlocConsumer and then the modified text will show to the right of the screen.
You’ve got it You’re done! With a separate UI with business logic you can alter the UI code, and then connect the Bloc into. It will operate in the same way.
Testing the BLoC Design Pattern
For testing the bloc, you require two packages:
- bloc_test
- flutter_test
Simply go to the folder for testing, make the app_bloc_test.dart file and begin writing the test.Inside we’ll test two requirements:
Initial state of application i.e AppState.empty().State changes when the button is pressed.
void main() {
blocTest(
'Initial State',
build: () => AppBlocBloc(),
verify: (appState) =>
expect(appState.state, const AppState.empty(), reason: 'Initial State'),
);
blocTest(
'emits [MyState] when MyEvent is added.',
build: () => AppBlocBloc(),
act: (bloc) => bloc.add(const ChangeTextEvent()),
expect: () => const [
AppState(
index: 1,
text: 'Changed Text',
),
],
);
}
Explanation
- blocTest is a part of the package bloc_test.
- Build() It returns an example of AppBlocBloc().
- Expect and verify in the sense that they are in line with the state expect(actual matcher, actual).
- Act: To insert an event to the stream
Github Repository: Flutter BLoC Simple Example
Feel free to copy your repository the flutter-bloc demo and begin to play around using the code.
Table of Contents
Tags Cloud
Frequently Asked Questions (FAQs)
- Events: Represent user actions or system events that trigger state changes.
- BLoC: Business Logic Component that contains the application’s business logic and manages state.
- States: Represent different states of the application, which are emitted by the BLoC in response to events.
- UI Components: Widgets that display the application’s state and respond to user interactions.