Flutter: Working With BLoC using Reactive Programming

In this tutorial, we will learn Managing App State in Flutter using BLoC pattern and Reactive Programming Rx. We will use Shopping Cart as an example in this post.

What is BLoC Pattern?

BLoC stands for Business Logic Pattern in which you put all your business logic side implementation in one place that receives events/data from Network parts, delivers to UI screens and back and forth.

This means UI part should not be handling any logic even including data validations. The reason for doing this is simple: Write Once Use Everywhere.

But BLoC is not only limited to this. It specifies using Reactive Programming as underlying technology to handle events/data flow.

So, What is Reactive Programming?

Well there are more than couple of terms that needs to be defined before Reactive Programming but simply to put: Its a way of solving problems in which you handle data streams asynchronously.

Describing about Reactive Programming will need a separate post and we don’t want to overwhelm you for now. We will write a separate post for this.

Below is the pictorial description of how BLoC pattern will work.

BLoC Pattern using Reactive Programming
BLoC Pattern using Reactive Programming

Shopping Cart Using BLoC Pattern

Now that we have some understanding of BLoC pattern, we will implement Shopping Cart using this pattern.

But before we start, lets describe what problem we are going to solve. Any retail store app will have a shopping cart and we will work on only two requirements:

  1. When user double taps a product, it should go inside cart.
  2. When user double taps same product, it should be removed from cart.

After defining above requirements, we list our Data Model and Actions.

  • Data Model: Product
  • Actions: Add Product, Remove Product

Lets define our Model first:

Add rxdart package to support reactive programming

Become A Flutter Expert With This Course

Now define Shopping Cart BLoC

Here, we try to process products selected by user. We pass product list to _productListController using updateProductList function and then receive data only from its stream. Remember that it doesn’t store any data. Any components that need selected product should subscribe to productListStream. It will emit productList to any listener it has subscribed.

Also, remember to close controller in dispose method.

Since we have implemented our business logic inside BLoC, we need to have access to it in any widget – at any level of widget tree. But How?

InheritedWidget to the rescue. We add our BLoCs into Inherited Widget and access their stream where we need it.

Learn How Inherited Widget works

And below is the widget that actually uses Shopping Cart BLoC

In above example, we showed the list of products and a floating button which will display number of products selected. When any product is double tapped, if it already exists in product list of shopping cart it will be removed else it will be added to it. Remember Add Product and Remove Product actions in our requirement.

StreamBuilder

You might be wondering what are those builder widgets and why are we wrapping both ListView and FloatingActionButton.

Definition

StreamBuilder: Widget that builds itself based on the latest snapshot of interaction with a Stream

Flutter Docs

StreamBuilder subscribes to the stream attached to it. That means, it will listen to events/data emitted by the attached stream and calls builder function every time new data arrive.

How it works?

Well remember that, productListStream is a Stream type. That means it will continuously emit any data added to its source. Our source is _productListController where we add data from updateProductList function.

In our case, every time we call updateProductList from Shopping Cart screen, we add new data to our source _productListController. And then subscribed to productListStream using StreamBuilder to update UI screen accordingly.

Running the app

As you see, we show ShoppingCart in our home screen. We provide ShoppingCartBloc to AppState and wrap our main app around it so that our app state can be accessed from any widget.

If you are new to InheritedWidget, we suggest you reading our tutorial in Basics of Inherited Widget.

Shopping Cart Demo using BLoC Pattern

Wrapping Up

We showcased the simple way of how to combine BLoC, Reactive Stream in Application State. Designing this way will help you scale our app easily. You separate all your business logic inside BLoC, put them in Application State and use it from anywhere. Any change in data will be reflected by builder function of StreamBuilder.

About the author