Managing Flutter State using Provider
By: Kenneth Carey
Tags: Mobile App Development, Android App Development, Android, Flutter, iOS App Development

Managing Flutter State using Provider

An introduction to Provider, one of a plethora of state management solutions for Flutter.

Who Should Read This

This post is intended for those new to state management in Flutter. The article assumes you are familiar with Stateless and Stateful widgets and can navigate between screens. If not, check out the links below.

What is State Management

State is the data your application needs to display or do something with. Data which may change.

For relatively simple scenarios, where the application consists of a single screen, we could use Flutter’s Stateful widgets and call setState() to rebuild the widget after we’ve modified some data or state. Remember, Flutter adopts a reactive model, rendering the user interface in response to state changes.

But consider the following scenario — a home screen which displays the currently signed-in user. That’s a two-screen application at a minimum and the home screen must somehow react to the action outcomes on another screen i.e. someone has logged in.

The above can be achieved by implementing a Publish-Subscribe pattern — where both screens are decoupled from one another and communication is achieved by one screen broadcasting a message, user sign in details, and another screen subscribing to that message. So let’s see how Provider can help.

So What Is Provider Exactly?

If you browse to the provider pub.dev package page you’ll see no mention of state management. Instead, it’s described as a wrapper around InheritedWidget and a quick search later you’ll see that InheritedWidget has something to do with propagating information down the widget tree. We’re getting closer.

In the context of state management, Provider is a widget that makes some value — like our user sign-in details— available to the widgets below it. Think of it as a convenient tool for passing state down the widget tree and rebuilding the UI when there are changes.

Concepts and Terminology

You need to become familiar with 4 concepts when working with provider.

Model — a class you create to encapsulate your application data and optional methods for modifying that data. This is what is made available to other widgets. Think of it as our message to broadcast. ChangeNotifier — provides model change notifications to listeners. Your model above extends this class and it’s how we publish or broadcast messages. Consumer — a provider package widget which reacts to ChangeNotifier changes and calls build method to apply model updates. This is our subscriber. ChangeNotifierProvider — a provider package widget that provides an instance of a ChangeNotifier to its descendant widgets. Consumer widgets need to know the ChangeNotifier instance they need to observe. That’s the role of ChangeNotifierProvider .

A Provider Sign-In App

We’re going to build the 2 screen app outlined earlier to show Provider in action.

▹ Create a new Flutter app in VS Code or using the Flutter CLI:

flutter create provider_login_app

▹ Next, we need to add the provider package as a dependency. To do this, add an entry for provider to the pubspec.yaml file.

▹ Install the provider package using the Flutter CLI pub get command:

flutter pub get

▹ You can import provider in your code using:

import 'package:provider/provider.dart';

▹ Open your main.dart file, delete the contents and then paste in the code below.

Points to Note:

Line 8: ChangeNotifierProvider is the widget that provides an instance of a ChangeNotifier to its descendant widgets. Here it builds an instance of our model class SignInDetailsModel . Line 41: Our HomePage consists of a Text widget which is wrapped inside a Consumer widget. The text displayed changes when a user is signed-in, the Consumer widget forces a rebuild when a notification is broadcast by our model class. Line 51: We define our Sign-In screen, consisting of a user name field, password field and a button. Line 84: Here we are using the Provider.of method to access the model instance. Provider.of obtains the nearest Provider<T> up its widget tree and returns its value. We then call signIn to crudely sign in the user and fire our notification, before finally transitioning back to the home screen. Line 127: This is our model class, where we encapsulate our user name and sign-in date. Notice how we extend ChangeNotifier and then call notifiyListeners() when broadcasting to any Consumer widgets that a sign-in has occurred.

Summary

State Management in Flutter is a complex topic, not least because of the number of possible approaches and packages available.

Here, we have attempted to introduce the reader to Provider and its concepts and also demonstrated how to incorporate it into an application in order to share state between screens.

Whilst briefly mentioned in this post, the techniques demonstrated here also promote lose decoupling - whereby the home screen and the sign-in screens are unaware of each other’s inner workings. They share a common model and utilise Provider to propagate and consume changes in this model.

https://www.twitter.com/FlutterComm