BLoC pattern in Flutter | FlutterDevs
By the title, you must have got an idea about what this article will be. As Flutter is growing day by day and so it’s developers and we as a developer always look for an easy way to deal with the code. So as the title speaks out loud we’ll be covering BLoC pattern in detail answering various questions like,
What is BLoC Pattern?
Why BLoC?
When to use BLoC?
and, How to implement BLoC?
But in this article, we’ll only be covering the first three questions in detail and the very next article will solely feature BLoC implementation with an example.
What is BLoC pattern?
BLoC a.k.a Business Logic Components is a design pattern presented by Paolo Soares and Cong hui, from Google at the DartConf 2018.
Initially, BLoC pattern was conceived to allow the reuse of the very same code independently of the platform: web application, mobile application, back-end. So yeah, this pattern was developed aiming to ease the workload on developers end while developing apps for a different platform with the idea of code reusability. Watch the video below to get more insight on the baby steps set by BLoC.
So, if you watch this video then you will understand how using BLoC you can share most of your code to different platforms.
To know BLoC in detail let’s first get to know about Streams.
Streams
In a general sense, a stream is a continuous flow or succession of anything.
For example, this is a stream of cats 😛
But technically speaking, Stream is nothing but a continuous flow of data.
Let’s take an example of Conveyor Belts. A Conveyor Belt has two ends, from one end an item is passed(input), then it is processed and after processing, it gets out from another end of the belt(output).
Key terms:
- Stream, the conveyor belt is called as a stream
- StreamController, this is what controls the stream
- StreamTransformer, this is what processes the input data
- StreamBuilder, it’s a method that takes stream as an input and provides us with a builder which rebuilds every time there is a new value of a stream
- sink, the property which takes an input
- stream, the property which gives the output out of the Stream
So now we got a bit of an idea about Streams. Back to Flutter, I think the one of the main hindrance one comes across while coding in Flutter is to deal with UI and everything else as in Flutter we don’t have any intermediatory designing language for the UI like in Android we have XML, instead in Flutter we write all the code at one place(traditionally). That’s where BLoC comes in play and helps remove this hindrance in an efficient way.
- BLoC not only solves the code sharing problem but also leverages Streams functionality in order to manage and propagate state changes in Flutter.
- BLoC helps us to separate Business Logic from UI. In other words, UI components should only worry about the UI and not the logic.
- So, even though Flutter lacked an intermediatory language for UI using BLoC one can separate both the things making independent on each other.
- If you’re an Android developer, then think of BLoC object as a ViewModel and of StreamController as a LiveData.
What does all this mean?
As already discussed BLoC makes use of Streams, we can infer the following things,
- The input is taken using the sink property
- The output is provided using the stream property
- Widgets send events to the BLoC via sinks
- BLoC notifies the widgets via streams
- Now that business logic and UI components are separated, we may change the Business Logic of the app at any time without any impact on the UI
- Similarly, we may change the UI without having any impact on the Business Logic
Why use BLoC?
Now that you got an idea about what BLoC is, you might be thinking why to use it for state management when there are already a few other ways to deal with it, let’s discuss them and see why BLoC is efficient out of all.
setState()
The setState() method notifies the framework that the internal state of the object has changed. Whenever you change the internal state of a State object, make the change in a function that you pass to setState:
setState(() { _myState = newValue } );
Calling setState notifies the framework that the internal state of the object has changed in a way that might impact the user interface in this subtree, which causes the framework to schedule a build for this State object.
Problems with this:
- The whole widget tree gets rebuilt every time state of even a single widget changes.
- It doesn’t help to separate the UI components and Business logic.
InheritedWidget
It is a special kind of a widget that defines a context at the root of a sub-tree and can efficiently deliver this context to every widget in that sub-tree.
As said, it can
- Propagate data down the tree
- Update widgets on rebuild
Problems with this:
- The state is set to final which means it is immutable.
- It doesn’t provide any dispose method to free the resources and to avoid data leaks.
Scoped Model
It is an external third party package maintained by Brain Egan. It is built on top of InheritedWidget offering a slightly better way to access, update and mutate the state. It allows you to easily pass a data model from a parent widget down to its descendants and also rebuilds all the children that use the model when the model is updated. To check for any change a method notify listeners() is used by Scoped Model.
Problem with this:
- As the model gets more complex it’s hard to keep track of when you should call notifylisteners().
So, all the above-mentioned approaches have one or the other demerits which didn’t stand as the best way of state management in FLutter and that’s where BLoC pattern stands to be efficient as it deals with all the demerits of these approaches.
Watch the video for a better perspective,
When to use BLoC?
To get to know when to use BLoC and when not to use, we must be aware of the concept of Local state and Global State.
Local State vs Global State
Taking an example you might have used: Imagine a login form, where the user has to enter the username and password and then there is an API communication to validate the credentials of the user upon which authentication works. So here and form of validation on the login form is considered as Local state since its scope is applied to this component only and the rest of application has nothing to do with it. While the API communication upon which the authentication of the user was depended is considered as Global state since it’s upon this authentication the entire scope of the app is dependent.
So, the basis on this local state and global state scope of the different methodology is dependent, see the table to know more.
Redux is also a state management approach. For dealing with local state BLoC is best recommended, while for Global state BLoC maybe used when the app is simple and not much complex but not recommended. For Global state, Redux is highly recommended.
So, this article gives you the necessary details about BLoC, from what is BLoC, why to use BLoC and when to use BLoC, the last question i.e How to implement bloc will be covered in a totally different article where Login form authentication will be performed using BLoC.
We hope this article was helpful to you and if there is something that we left then do let us know in comments and also if you want something else for us to cover in Flutter.
FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, and Twitter for any flutter related queries.