Provider State Management in Flutter
Flutter is a declarative framework. In contrast, to the imperative framework, Flutter does not allow to change the widget, which is mostly the UI component on screen, once it is defined. It is to make widget light weighted. However, the widget can be rebuilt with a different appearance or data in it, and the end result is same, the change in UI. For this, we use Stateful widget, and we call setState(), whenever there is some change occurred in state of widget. Calling setState() tells the Framework that state of the widget is changed, and widget must be rebuilt, hence the widget gets rebuilt, which is same like changing the widget, however there is the difference of mechanism.
Managing State using setState() starts becoming horrific as the code grows. because whenever you need to change the widget’s UI, you have to call setState() inside the changing widget, so that it gets rebuilt, and since application is composed of hundreds of different widgets, so there could be hundred different points where you have to take care of calling setState(), and managing state. Moreover, your front end logic will be scattered in different places in UI code. So, using this raw technique to manage state is not a good option, we have a better approach to manage state, which is not just Easy but Effective, called Provider State Management.
Provider
Provider State Management, which is recommended by Google a well, mainly provides you a central point to manage the state, and to write front end logic.
Provider Components
There are three components related to this Provider State Management that we need to understand.
- ChangeNotifier.
- ChangeNotifierProvider
- Consumer
Now, there are different techniques to understand this provider approach, however, for the sake of simplicity, we are discussing the below variant of Provider State Management.
For Every Screen of Flutter application, we make a central point for managing state which is called a ChangeNotifier, which is just an ordinary class that extends ChangeNotifier class. It contains all the state data that are being used by different parts of corresponding screen. Now if something is a ChangeNotifier, and some of its data gets changed, it notifies the framework that the screen which is using the change notifier, needs to be rebuilt, since the corresponding screen’s state, ChangeNotifier, is changed. If you have already worked on MVVM than you can think your screen as View and ChangeNotifier as ViewModel or Controller in case of MVC.
For the implementation, Let’s consider a scenario. Say a person wants to apply for driving license, and there is a very simple form that he has to fill using our Flutter mobile application in order to know if he is eligible for applying or not. The Criteria for eligibility is pretty simple, one must be at least 18 years old in order to be eligible.
So our Flutter application would be a single screen application, on which there would be a simple Form contains TextField. There are two extra widgets on screen as well, one is Circle, which is orange by default, but after submitting form, if the user is eligible, then the circle would turn green, however if not, then red. Secondly, there is a Text widget at the bottom that will show the message that would change based on user input, however, by default it will show “You have not give any input”.
Above is the Code for Eligibility Screen without Provider (Not Final). So, we have done with the UI part, and now we can make ChangeNotifer against above screen.
ChangeNotifier
Now let’s make ChangeNotifier against above screen that would contain all the state data related to that screen.
Now in the above ChangeNotifier that we have made against Eligibility Screen has just two state data in it first String _eligibilityMessage, which is showing message, after processing the user age, and, bool _isEligible flag, which is to change the color of the circle status indicator.
In ChangeNotifier, we made a method checkEligibility() which takes age as a parameter and after performing the logic it changes the state, i.e., if user is eligible then it will call eligibleForLicense() else it will call notEligibleForLicense().
The Most Important thing is calling notifyListeners(), whenever you change the state data in ChangeNotifier. If you will not call this method, the state change would not reflect in the UI. The method notifyListeners() tells flutter to rebuild the screen which is using that ChangeNotifier.
ChangeNotifierProvider
As we have made EligibilityScreenProvider ChangeNotifer against the EligibilityScreen, now we have to connect this provider with the screen, or we have to use this provider in EligibilityScreen. For this, we use ChangeNotifierProvider, a widget, that provides the instance of ChangeNotifer to the screen, and thus we can access state data of the ChangeNotifier in the screen. We just need to wrap the EligibilityScreen inside ChangeNotifierProvider for this, code is given below.
Consumer
It is not necessary that all the part of the UI in EligibilityScreen will be using the state data from EligibilityScreenProvider, and thus needs to be rebuit. It may be possible that 50% of the UI of any screen, not in our case, not needs to be rebuilt. So, Consumer, which is a widget, allows to observe the state changes from ChangeNotifier in a particular part of UI, and thus only observing part of the UI will get re-rendered.
At line 10, We have used ChangeNotifierProvider widget, so that we can access what’s inside the ChangeNotifier. We need to give the type of your provider in type parameter of ChangeNotifierProvider ChangeNotifierProvider<EligibilityScreenProvider>.
At line 19, We have used Consumer widget, so that whatever inside it gets rebuilt whenever notifyListener() is called from EligibilityScreenProvider ChangeNotifier. At Line 20, we have 3 thing in the builder method, the first one is BuildContext context, which we have in every builder, second the instance of EligibilityScreenProvider provider, which you can use to access the properties of EligibilityScreenProvider, and last one is just for the optimization, which you can skip for now.
Below is the Code of main.dart
Awesome So that’s all from it. If you really found this article useful and you want to learn more from me, then you can head over to my YouTube channel Easy Approach, over there you can find hundreds of different videos on Flutter, and a comprehensive and easy Flutter video series.