Flutter — Provider (Explanation)

Deepak Goyal
5 min readNov 2, 2020

The provider package is used almost by all developers (fresher or experienced) and in all types of projects (simple or complex). Google also uses and recommends the provider package for state management. Check out this video from I/O’19 https://www.youtube.com/watch?v=d_m5csmrf7I&ab_channel=Flutter

Why Provider?

We have Stateless and Stateful widgets in Flutter. The real app or product (made in flutter) has several screens and each screen is a widget in a flutter. Let’s consider the registration process in the app which consists of several screens.

Suppose there are 5 screens for registration where a new user has to provide some details on each screen. In the last screen of the registration process, you need all the data entered by the user to save in the database. So when you go from screen1 to screen2, you have to pass the data of screen1 to screen2. And when going from screen2 to screen3, you have to pass the data of screen1 and screen2 to screen3 and so on…

Probably, the way to pass the data to the screen is by having parameters in the constructor.

This will become complex as you have more screens and more data. So here it requires a simple way to do that and luckily, flutter provides a type of widget which is InheritedWidget and this can solve the problem. But in general, inherited widgets are difficult to understand and can have a lot of boilerplate code. Read more about inherited widgets at https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html

The provider is a wrapper around InheritedWidgets to make them easier to use and more reusable.

How to use the Provider?

Flutter provides ChangeNotifier class which provides notification to the listeners that the value is changed. Provider provides the ChangeNotifierProvider widget that listens for changes.

The above with provider will be like:

In the screenshots, you can see that there is no need to pass the user data in the constructor of screen2 now. The data can be accessed using:

Provider.of<UserModel>(context);

But you have to wrap your every widget/screen with ChangeNotifierProvider where you need to access the data of UserModel. Otherwise, you won’t be able to access the UserModel. This is fine if you want to use your model on a few screens. But if you want to use your model in the entire app or a large number of screens then you can create or initialize your model by wrapping your Material widget (main) with MultiProvider.

MultiProvider(
providers: [
ChangeNotifierProvider<UserModel>(create: (_) => UserModel()),
],
child: someWidget,
)

Now you don’t have to wrap your each registration screen with the ChangeNotifierProvider widget. You can directly access the UserModel on any screen with Provider.of<UserModel>(context);

But here are some issues:

  1. You have to reset your user model on the screen1 before going to screen2 and update the model with the data entered by the user on screen1. Otherwise, your model will have the data from the already registered user (if another user is already registered from this session). But this is not a big problem.
  2. We need the user model only on Registration screens but we have created a provider for the entire app using MultiProvider.

We can solve the above problems by using a nested navigator https://api.flutter.dev/flutter/widgets/Navigator-class.html#nesting-navigators

With the nested navigator, we don’t have to provide the provider for the entire app but for current navigation. So we will create a separate navigation for registration screens.

Now every time screen1 is opened, it will have separate navigation and a new user model. The next screens such as screen2, screen3, etc., can access the user model by Provider.of<UserModel>(context);

  1. If you have to use your model in the entire app then initialize the provider by using MultiProvider
  2. If you want to use your model in a separate process then try to use a separate navigator.
  3. Otherwise, wrap your every screen with ChangeNotifierProvider of the same model.

listen: true or listen: false

When you access the provider using Provider.of<UserModel>(context); you can also pass the parameter listen with the value of true or false. By default, it is true.

true means, you want to listen for future changes in the model object and if there is any change in the user model then it will be notified with notifyListeners();

false means, you don’t want to listen for future changes in the model object and if there is any change in the user model then it will not be notified.

Thanks for reading the article. Let me know if you have any questions.

--

--

Deepak Goyal

I’m a Software Engineer. I love programming. #java #android #kotlin #dart #flutter #firebase