In the last few years, as a UI developer, I got a chance to work on various technologies like Angular, React, and Android. You can find out about them listed under our portfolio page. Recently, I got a chance to explore the world of Flutter and it has mesmerized me the most. However, the most interesting topic for me is ‘State Management in Flutter’. As I started diving deep into the depths of this framework, I was impressed.
It’s a hybrid framework, getting popular now, to build responsive web applications and mobile apps. Additionally, we can use the same codebase to develop iOS, Android, and Web applications. State management is a key concept for any application framework. If you are familiar with React, the term ‘State’ should be familiar to you. If not, that’s ok, you will know about it in this blog 🙂
So, in this, I would like to explain how to manage the state with an example. Let’s begin…
The state refers to the data that the widget holds, that may change during the lifecycle of the widget. Whenever the state changes, the build method is triggered which renders the UI with the updated state.
Additionally, there are several approaches to manage state in Flutter. One of them is using the Provider package. Without any further delay, let’s construct a sample screen that takes data from API and uses the Provider package to get notified when the data is ready and displays a list of users.
Note: In this blog, we are using the Android studio.
Create a sample flutter application as demonstrated in the docs. Now, we are ready to implement the actual screen.
First, let’s start by importing the necessary packages for the provider and HTTP. Add the following dependencies under the dependencies in the pubspec.yaml file:
Now click on Packages get to get the dependencies. Let’s go ahead and create the UI part for our screen. This is my lib folder structure:
Then, as the folders are self-explanatory, let’s create two widgets under the views folder with the names:
Replace the contents of users_list.dart with the below code. Here, we are showing a sample text on the list screen, which we are going to change further.
Now, let’s call this widget from main.dart file. Replace the contents of main.dart with the below code:
If we run the app, it will show a screen with Users list heading and text placed at the center of the screen like below:
To get a list of users, we are using the users API from https://jsonplaceholder.typicode.com/, which returns a JSON array of user details objects. However, In our app, we will show the names of the user in the list item. Create a model file user_model.dart in the models folder and add the following code:
Here, fromJson creates a new user instance from a map structure. However, this is part of the json serialization process. Create user_service.dart file in the services folder and add the following code:
Here Future<T> indicates that the function will take some time for the result to be ready and the data of type T will be available in the future. In our example, T indicates the list of UserModel objects. Once the response is ready, we are using the jsonDecode method of dart:convert to decode the response as list and we are returning the final data. Here, we are throwing an exception if the statusCode is not 200.
Now, our data is ready. But how are we going to notify the UI that the data is available now? Yes… using the Provider package. Create a view model user_view_model.dart and add the following code:
Here, the UserViewModel class is extending the ChangeNotifier class of the provider package. ChangeNotifier class helps us to subscribe to the changes in class that extend it.
ChangeNotifier provides a method called notifyListeners(), which we use to notify the listeners of this class to rebuild the UI with the new changes.
Here, we are using Future<void> as the fetchUsers() method does not return any data. Once the data is ready in the users variable, we call the notifyListeners() method.
Now that we have the view model class ready, we need to have subscribers who subscribe to the data and get notified of the data changes.
Let’s go back to the main.dart file and make some changes so that the child listens to the changes. Change the body property of the scaffold and import the files as follows:
Here, we are importing the provider package and using ChangeNotifierProvider and Provider.of(context) to listen to the changes and update accordingly.
We have added the ChangeNotifierProvider class of the Provider package to the body. It listens and exposes the ChangeNotifier class to its descendants and rebuilds whenever the notifyListeners method is called.
In the create method, create an instance of the UserViewModel class that we have created previously.
Open users_list.dart and make these changes related to the provider package.
As the initState() is the first method that will be called when the widget is created, we are using the Provider.of() from the provider package to access the View model class and calling the fetchUsers() method. However, In the build() method, we are showing a loader until the data is ready. We are passing the user data to list item class through the constructor of that widget.
Then, create the list item UI in the users_list_item.dart file as below:
Here, we are getting the model data through the constructor. And we are using the Listview to display the data from the model.
Run the app and see the result…
Yaayyy!!! Now you can see the loader and list of user names.
Now that you are aware of the provider package usage and API implementation, go ahead and play around with the State Management in Flutter.
Additionally, you can try an example of creating a to-do list screen where you can edit, delete or add a new task to the list.
Hope this blog helped you understand State Management in Flutter. Happy Coding 🙂 🙂 🙂