Flutter State Management Approach
Which state management approaches is the best?Last updated: July 22, 2021
When it comes to choose any architecture, design pattern or this kind of similar kinds of things it always comes down to preference, choice, need and applicable scenario and most of the writings ends with up with a solution that is very confusing, and most of the cases pros and con, applicable scenario aren’t described. Here I’m trying to describe a bit according to my little research and knowledge.
List of state management approaches
- BLoc
- Riverpod
- Provider
- Redux
- Mobx
Let’s start with BLoc
BLoC pattern is loosely defined, there are a dozen implementations. However the core principle is to use the stream in the back, StreamBuilder in the UI, to build up reactivity around the stream. I suggest you read Boelens blogs.
The main advantage of the stream is that each StreamBuilder listens to a stream, and only update when that stream changes. Therefore the stream solved the problem of setState, and achieved clean reactive binding between back and frontend.
One of the BLoC implementations uses pure reactive programming in the backend with the help of RxDart, though, both its advantage and disadvantage are RxDart, as your entire backend is programmed “stream fully”. The pure BLoC is very flexible, you can strictly implement event_stream →BLoC →state_out, you can also value_stream →BLoC →value_stream_out
Another popular implementation is the flutter_bloc package, which maps the event to state, and your backend is not strictly speaking filled with the stream. (personally, I think its an entirely new architecture that has redux-ish event->state for state management, and MVVM-ish for app structure, BLoC-ish using stream and stream builder to bind the state to UI).
Riverpod
Riverpod is a rewrite version of Provider, idea is almost same but with lots of benifits. Currently I prefer it more than Bloc or Provider, those who are using provider they should consider moving to Riverpod, instead of Provider.
Provider
Provider package has two huge part, dependency injection, and various value consumption. For example, you can use Provider to inject your BLOC into UI, and simply using a stateless widget. For example, the flutter_bloc package has adopted Provider into its highly customized bloc_providers.
For most people saying Provider, often means using foundation: ChangeNotifier as a mean of state management. And using the Provider.ChangeNotifierProvider to inject and binding to the UI. Thus MVC, MVVM are both very good architectures. It is indeed simple, however, ChangeNotifier has a serious problem, say you have class A extends ChangeNotifier. And this class A has three state variables, a, b, c. Let’s assume in your current page you have 5 elements/widgets listening to classA, then whenever any of a, b, c notify changes, all your 5 elements need to update. Effectively, your UI is reactive to the ChangeNotifier class, instead of a member of ChangeNotifier class. Ofc, you can split it as small as possible, some waste in UI update is inevitable. There was a proposal in dart issues that suggests spin-out the ValueNotifier from ChangeNotifier, but it’s long-buried anyway.
Its simplicity is mainly due to the fact that you can maintain the traditional way of programming (non-reactive)
Mobx
Furthermore, there is another framework which has been ported from the ReactJs world, called MobX. It achieves reactive programming different to Stream/RxDart that it is reactive to value. In another word, your UI can listen to a member of a class. None the less, you still need programming in a reactive way. But that’s another story.
Why I choosed Bloc?
- Lots of people went with provider because they do not want to accustomed with Rx, which is not the case for me, I’m a fan of Rx anyway, I have been using RxSwift, RxJava for many days.
- Those flutter developer have JS background they sometimes chooses Mobx or Redux as they are already used to the idea which isn’t the case for me.
- I already like MVVM very much.
- Many devs avoids Bloc because it introduces boilerplate codes, but by using flutter_bloc package I can eliminate the fact.
- Google introduced it in 2018, so I first learned it then fell in love with it, now it’s a long term relationship.
Conclusion
For example, does your app need to behave/analysis/record UI events? if so, you need to use a event->state framework like redux, fishdux, flutter_bloc, or do it yourself with BLoC, MobX, etc.
Further, does your UI need distributed stores? if so, redux is a terrible choice and for instance, flutter_bloc is much better.
How many people are in your team? for example, you cannot expect a dozen people all write code the same way without strict guidelines. Simple state management could result in horrific spaghetti in a large team.
How complex is your state, for example, if your view store only has a few members, who care some duplicated updates in the UI and why not use setState or ChangeNotifier.
And if your backend is filled with streams, why not just use RxDart with BLoC pattern?