Flutter Provider & ChangeNotifier Architecture Guide

Julien Grand-Chavin
3 min readDec 23, 2019

--

In this article, I will give you my vision of a good architecture in Flutter. For me, the complexity with Flutter is how you manage data and UI cleanly.

During the last 2 years, I have tried many Flutter architectures. I started with a vanilla architecture like every one, then I used the BLoC Pattern a lot, I also did a little of MobX and ScopedModel. But once I tried the Provider & ChangeNotifier architecture, I realise I had found the architecture I was looking for.

What’s a Provider?

A Provider is a Widget that will own data and will be available everywhere in your application with a BuildContext. It’s a place where you can « save » (for example authenticated user information) and get it in any Widget without making any other API call or anything else. (for Angular developers, you can call it a Service).

What’s a ChangeNotifier ?

ChangeNotifier is a native class from Flutter. We’ll use it to notify our View when one or more variables change in its ViewModel. It prevents to use the ugly SetState() function directly in our Views which would result in unmaintainable code.

Let’s see an architecture overview

Provider & ChangeNotifier Architecture overview

So this this how this architecture works, globally. The arrows represent communication between widgets.

Let’s define some terms:

View and ViewModel

A view in Flutter is a Widget that contains only UI Widgets. To manage this view and give it data and functions, you will need a ViewModel. To summarize, one ViewModel manages one View (you could also called it Screen).

Repositories

Repositories are classes where you have all your functions to query data from database or API.

Models

Project’s Objets classes

Utils

Everything you need to help you with classes. Like for example DistanceUtils for distance functions, etc.

Constants

ProjectColors, ProjectTextStyle, etc.

Enums

All enums you need in your project

How does it work ?

In this diagram, we can see that Providers are linked to every widget even MaterialApp. It’s because MaterialApp rebuilds and doesn’t keep state at every Navigation move. You cannot retrieve data from a Widget that is not under the navigation stack, which means you need to put your Providers over it.

In this case we have AuthProvider over other widgets because most of the time, we need auth information in other Providers.

Then you can retrieve every Provider in every ViewModel to show data in your view.

Go to the code side 🛠

First of all, let’s see my directories organisation:

Directories organisation

Pubspeck

In your pubspec, you only need to add one package : Provider (https://pub.dev/packages/provider#-readme-tab).

main.dart

This example shows how to make your Provider available in your whole app (with a AuthProvider under).

base_provider.dart

The base provider is here just to provide the dispose method or, in our example, to provide the AuthenticationProvider to other Providers.

base_view_model.dart

The BaseViewModel’s role is to hold all the providers the app needs in order to give it to ViewModels and the ChangeNotifiers.

example_screen_view_model.dart

In this example we see how to initialize and retrieve a value from a Provider and how to notify our view that a value has changed.

view_model_provider.dart

This Widget’s role is to provide a ViewModel to our View. We’ll see how use it next.

example_screen.dart

And now with our ViewModelProvider we can pass data and change data to our view 🎉

This is the end 🎬

I hope this little guide will help you !

You can find a project starter with this architecture here: https://github.com/jgrandchavin/flutter_provider_architecture_starter

--

--

Julien Grand-Chavin

Co-Founder at Revolt Games | Developer who loves building cool and high-quality products 🙌