Flutter Blocs: A Simple Introduction

A step by step guide to using Flutter Blocs in your project

Sumit Ghosh
Better Programming

--

Photo by Kellen Riggin on Unsplash

Are you finding it difficult to understand the working flutter_blocs library? Or you know it but might be getting confused while implementing it? Don’t worry we will go over step by step and understand everything in detail.

Flutter blocs provide a straightforward approach to handling different states in an app, once you understand it, it's easy to use and scale for any size of applications

Why do we even use Flutter Blocs?

Bloc makes it easy to separate presentation from business logic, making your code fast, easy to test, and reusable. — Offical Bloc documentation

Flutter Blocs simplifies doing state management in the app, it provides simple APIs to use, that abstracts lots of details and makes state management easier, it's one of the most popular state management libraries in Flutter and is actively maintained by Felix Angelov and other open-source contributors.

As the name suggests Blocs handles all the business logic, be it interacting with the data layer to show something on UI or some complex computation.

But, what is State Management? Can’t we ignore it, I mean we don’t use it on Android or iOS?

No, we can’t, because Flutter is a declarative framework, it builds its UI to show the current state of the app, so whenever the state of the app changes we trigger a redraw of the UI, so basically for each state there is some UI, or as the official docs say, “UI is the function of the application state”.

for example, —

  • Network not available State, you show a snack bar.
  • Fetch data State, you show a Loading indicator
  • Data is Fetched State, you show a Text widget with data, and so on.

By the way, there are multiple state management solutions available in flutter but flutter_bloc is the most popular one.

We will add the flutter_bloc plugin as a dependency to our app, check for the latest version of the library, and add it to the pubspec.yml file of your project, under the dependencies section, the indentation should be proper, check the image below.

We will add a bloc extension to our IDE (available for both VSCode and Android Studio) as it helps in generating bloc files and reducing a lot of boilerplate.

Once you have added an extension, create a folder to store the bloc files and do Cmd+N on the folder, you will see an option of Bloc Class in the drop-down,

Provide a name to your bloc, also you can choose to use Equitable. This generates three files.

We will go over them one by one, but before that let’s look at a very simple diagram to understand, each of these components and How they interact with the UI?

Photo from Bloc library Offical docs

So it is simple and straightforward, isn't it? Four steps are involved in this,

  • UI triggers an event.
  • Bloc read’s the event runs some business logic.
  • After the computation is done, Bloc then emits a state.
  • UI listens to the state and updates itself accordingly.

These are the three files, — Bloc, event, and state, go over the code snippets you can ignore “Will be used later”, comments I will be referring them in the next sections.

As the code snippets have a comment on each line, hope you got an idea of what these three files do, also visualize these components as shown in the bloc architecture diagram above.

So we have defined the Bloc Layer now let’s build a simple UI to see, how we can use this LoginBloc?

So in UI, we have added a text and button, on the tap of the button we will change the text. We will trigger an event on the button which will get a text from Bloc that we will display.

Wait! How will LoginScreen know about LoginBloc ?

Ah! Flutter Blocs already have a very elegant solution for this. As widgets are all around in Flutter, flutter blocs provide lots of useful widgets, as we progress with the example we will look into some of them in the next section.

We will go over the three questions to start using the Bloc, —

1. How to make Bloc available to the Widget tree (UI)?

The Widget which gives this functionality is the BlocProvider widget, BlocProvider makes the bloc available to the entire Widget tree, which is passed in the child parameter.

In the above code, we create a new instance of the LoginBloc, and as a child, we pass the instance of our LoginScreen , so Bloc Provider makes the LoginBloc available to the Widget tree of LoginScreen , Bloc Provider automatically handles the closing of the Bloc.

2. How to trigger an Event from UI on some action?

Now that we have Bloc available on the Widget tree we can access it from anywhere, there are two ways to do that, —

a. Using context,

context.read<BlocA>();

b. Using Bloc Provider,

BlocProvider.of<BlocA>(context)

But what is the difference? When should we use which one?

There is actually not much difference both are almost the same, but the first one is defined as an extension on the BuildContext, so it’s easier to use. Proceed with whichever you like.

Let’s add a button tap event on the Bloc, —

Note: — It’s important to pass the correct type of the Bloc, because it tries to lookup the tree to find the instance of that type, you can read more on this here.

Coming back to the Event, see how easy its to trigger an event from UI, we just call the addmethod on the Bloc, and pass an instance of an Event.

Now we need to go back to the Bloc and check if we have registered this event which is sent from the UI, on receiving this we will emit a State with a String to show on the UI, you can refer to the Bloc code attached above, just uncomment all the code with the comment “will be used later”. Great that’s it.

3. But how will UI update itself when a new state is Emitted?

Yes, you guessed that right, there is a widget for this too. It’s called Bloc Consumer.

Let’s go over the BlocConsumer, though the above example contains the entire LoginScreen , but for now, you need to focus only on _buildScaffoldBody function.

If you notice the BlocConsumer , have four arguments let’s go over them one by one,

builder — It rebuilds the widget tree in response to the state changes, which means whenever you emit a new state it will rebuild the widgets so that you can use the value sent in the state that is emitted from the Bloc. So in this example, we have passed a text from the bloc in the UpdateTextStateand used it to so on the UI, this state is emitted whenever the “Tap me!!” button is tapped.

listener — So whenever a state is emitted the listener also gets invoked, but unlike builder, it doesn’t return any widget. It gets called once per state change, that’s why we generally use a listener that happens once whenever the state changes, like showing a snack bar, dialog, bottom sheet, or navigating to the next screen.

buildWhen — This is an optional parameter that provides previous and current states and returns a boolean, so if we return true it will call the builder, or else it won’t if you don’t use this parameter the builder will be called for each state change.

listenWhen — This is similar to buildWhen but used to control the Listener, if it returns true then the listener gets called.

So in our example, we are using Listener for ShowSnackBar state, which shows a snack bar with a text to display when the button is tapped. and we are using builder for LoginInitial , UpdateTextState , which updates the text on the screen when a button is tapped.

Another interesting point to note is that BlocConsumer takes in an optional parameter bloc, if you don’t provide it, it will try to lookup using BlocProvider and the current BuildContext . So if you missed injecting the Bloc (Question 1) it will throw an exception.

There will be cases where you either want to use builder or listener , for such cases there are different BlocBuilder and BlocListener widgets, feel free to explore them, also Flutter blocs provide some other helpful widgets but that’s for some other day.

Summary

  1. Build a UI (you have some business logic to run?).
  2. Create a Bloc (Bloc, Event, and State classes).
  3. Bind them together (Remember the three questions?).
  4. Use BlocProvider to initialize the Bloc and make it available to the widget tree.
  5. Use context to lookup the Bloc so, that you can add an event.
  6. Perform your Business logic in the Bloc and emit the result.
  7. Use BlocConsumer , BlocBuilder , BlocListener , to listen to the state changes and perform actions accordingly.

Useful Resources

--

--