What does the State Management in Flutter mean?, how can I apply it?
Link to see this article in Spanish.
Oh yes! We are finally getting into a bit more advanced topics as a community.
We have shared simple topics such as managing scrollable widgets and more advanced topics such as clean architecture in Flutter in this blog. You should subscribe if you haven’t because what’s coming up are topics that are more interesting than the previous ones. The last time we published an article that explained a Provider´s meaning and Christian left us this comment:
This means: “we want an article about state management because I do not know what state management is and what it is not.”
That question is really valuable. They told us that the Provider is a state manager in others forums, but as we saw in the last article it is not like that; its versatility makes them use it for that purpose, but it is not the main intention.
So what actually is state management and how can we use it?. I will clarify all your doubts and we are ready to always have state management in our applications.
Important note: Firstly, you must read the article that explains the Provider for a better understanding (link).
What is state management?
The dictionary defines it as the “situation or way of being of a person or thing, especially the temporary situation of people or things whose condition is subject to change.”
If we take this definition to an application, we can say that the State describes the current situation of the application or its components. For example, when the user clicks on a checkbox changes the current position of the application. Therefore it changes its State.
Another example could be when making an API request in the back. If the information is ready, we offer the received data on the screen to have the loading state (loading) and the loaded State (loaded). While we are loading the information, we show a circular indicator.
There are at least two determining States within applications that you should be aware of; ephemeral and application states. Let’s see each of them:
Ephemeral states
An ephemeral State (sometimes called UI state or local State) is the State that can perfectly hold a single widget. For example:
- Currently selected tab in a BottomNavigationBar
- CheckBox Selected
- One Button Actuated
Being conscious of that, we must think that the ephemeral State does not need to access the other widgets in the tree.
Application status
This State is not ephemeral, it needs to be shared throughout the application and sometimes you want to keep it between user sessions (sometimes also called shared State).
Application status examples:
- User preferences
- Authentication status
- The shopping cart in an e-commerce application
However, Let’s make the following mental map to know when we are facing an application state or an ephemeral state:
States Manager
State managers allows people to manage them customer interactions in our applications. 🧐 It is not necessary to use complex strategies to manage ephemeral states, you can use the usual State and setState for its administration. That is why its scope is encapsulated in the widget. Then it’s not required by anyone else in the widget tree.
To manage the application states is better to use a strategy that allows you to easily manage them. Do you want to see an example? We’ll see that in the next 🥲… section (let’s not think we’ll make you wait for another article 🤣).
State Management Example
Well, let’s start to see the theory applied to the code.
Managing an ephemeral state
You have already seen this in the hello world of Flutter:
When the user clicks on the button, it increases the counter, which generates an increase in the number and redraws the related text. As seen in the _incrementCounter function, a setState is used. Does this mean that element is implemented with bad practices? Of course not.
In this scenario, no one else in the application used the value of this counter. If the scope of the State is encapsulated in the widget, there is no need to implement a more advanced strategy.
Managing application state
We consider the following scenario:
Let’s make a simple application. It will have three screens, the first one where the client will enter the username and password. Another is where an API request will be made to obtain a list of albums so the user can select the appropriate one they want to buy and, finally, a purchase screen for the selected items.
I like this example because it allows us to create ephemeral and application states. Before showing the code, let’s think about the application states. What do you think they would be?
However, can you think of some ephemeral states? Think, for example, of the text field controller and its states or buttons that only execute instructions in their context. In this case, we will discuss the following: Authenticated user and a list of albums selected by the client.
Now we think about the following. In the previous article, where we explained the use of Provider, it was clear to us that we use it to share information throughout the widget tree. Therefore, it is advantageous to handle the states of the application (because it needs to access a state variable from anywhere in our application).
However, we think about the user’s name. Is it a state of the APP? of course not. But it is relevant information that we would like to share throughout our widget tree, and we can use Provider to share it. We can even use Provider for dependency injection.
Now, let’s go to the code🧑🏽💻.
Let’s go first for the providers:
user_provider: Provider of information related to the user. Here,the Provider is used to share relevant information (lines 5,6,7) and manage the session state (lines 4,7,12).
cart_provider: Then, we have the Provider of our shopping cart. Before the change in the shopping list, all their children are notified. And so it should be because the number of products and their information is part of the status of our shopping application.
album_provider: This is a provider that is not doing state management. It is only used for dependency injection and sharing across the widget tree.
app.dart : As we see in lines 21–29 our providers are configured. The dependency injection is done in case a mock is desired instead of the API in line 23. It could be configured there.
login_page: the login controller is started in line 14, but in line 24 a reference to the User provider is started, which allows when to check the status and information of the user to be updated (lines 54, 55) while pressing the button (line 53).
This information can then be accessed from any widget in our app.
Now let’s see the management of the shopping list:
As you can see, we are not managing the status of the checkbox from the Provider (although it could be done, do you dare to make a fork and do it? 🤓). But we are registering the most important thing: removing or adding the element to our shopping list and the item’s current status (selected or not selected).
You have an activity that reviews the repository in this link, and you can see all the elements of the example application.
To conclude:
I hope that this article will give you the right information regarding state management to understand the differences between ephemeral and application state. At the same time, you can use use it in all your solutions.
I give you a big hug and if you liked this article, give us +50 applause, please.
See you in the next installment 🧐. Tell us in the comment box what you would like us to analyze in the following article.