Easy State Management with ValueNotifiers and Inherited Widgets in Flutter
Tags: flutter, mobiledev, programming, dart
Published: 2021-05-26 14:27:47

## Introduction

The flutter ecosystem has grown rapidly in a few years, seeing it grow from just a mobile development framework to support both web and desktop development.

Building mobile apps using flutter, there are tons of state management libraries or packages to choose from which can be a beginner's nightmare.

In this tutorials we will be managing our own app state with only InheritedWidgets, ValueNotifiers and ValueListenableBuilders.

## What we will be building

We will be implementing a favorites list from a list of fruits.

#### At the end of this tutorial you should

- have a good understanding of InheritedWidgets, ValueNotifiers and ValueListenableBuilder and how they can be used to manage state in your flutter applications.
- be able to use them to manage you own application state without needing StatefulWidgets or external state management libraries or packages.

So let's dive right in...

### Creating your flutter project

- Create a new flutter project. I will not go into details of creating a flutter project since it is pretty straightforward.

Here is a look of our boilerplate after cleanup

{% gist https://gist.github.com/solnsumei/23105c6c1a7002593771912352e613cf file=main1.dart %}

Now lets take a look at the ValueNotifier with the ValueListenableBuilder and how they can help us manage state in our flutter apps.

### Implementing a Simple ValueNotifier

**ValueNotifier** class is a subclass of ChangeNotifier which manages the state of a single value and notifies listeners when the value changes. It works with the **ValueListenableBuilder** widget which automatically listens to changes on the valueListenable and rebuilds enclosed widgets accordingly.


{% gist https://gist.github.com/solnsumei/23105c6c1a7002593771912352e613cf file=main2.dart %}

If you run the code above you discover that the counter value changes but the app does not display the changes. This is where the ValueListenableBuilder comes in.

**ValueListenableBuilder** is a widget whose content is always  synced with a ValueListenable. The ValueListenableBuilder requires two arguments, a ValueListenable, which is a ValueNotifier instance, and a builder, which is a callback that rebuilds the widget based on the changes to the value being listened to. Implementing that in our code will look like

{% gist https://gist.github.com/solnsumei/23105c6c1a7002593771912352e613cf file=main3.dart %}

Now that you know what a valueNotifier and valueListenableBuilder are and how to use them, let's get started on our project.

### Implementing a Custom ValueNotifier

The above example showed a simple use case of the ValueNotifier, for more complex and custom implementation, one will need to extend the ValueNotifier class.
Now, lets create our custom ValueNotifier class


{% gist https://gist.github.com/solnsumei/23105c6c1a7002593771912352e613cf file=favorite_notifier.dart %}

Because we are interested in a list of favorites, we made our **FavoriteNotifier** class inherit from ValueNotifier<List<String>> and implemented the constructor.

Next we add methods to add and remove from the favorites list.

{% gist https://gist.github.com/solnsumei/23105c6c1a7002593771912352e613cf file=favorite_notifier2.dart %}

Notice the use of the **notifyListeners** method in each method we implemented. Without it the listeners will not get notified when the value changes or is updated.

There's a problem, how do we pass our custom valueNotifier down our widget tree to maintain the same instance and not multiple instances? Enter **InheritedWidgets**, but before then lets update our UI code.

{% gist https://gist.github.com/solnsumei/23105c6c1a7002593771912352e613cf file=mywidget.dart %}

We have completed our UI and included a FavoriteCount widget to show how many items are in our favorites list, as well as a list of fruits to our app page.

Running the app now will display a list but clicking on any of the items will do nothing.

### Wrapping it all with the Inherited Widget

**InheritedWidgets** allow us to receive data from widget ancestors without having to pass it down a widget tree.

We can create our own Inherited widget by extending the InheritedWidget class, adding the data we want to share, and creating an `of` method to call in our child widgets whenever we want to access the data.

Let's implement that in our code.

{% gist https://gist.github.com/solnsumei/23105c6c1a7002593771912352e613cf file=favorite_state.dart %}

Now lets wrap our MaterialsApp with the FavoriteState so the data it holds will be available in the child widgets also.

{% gist https://gist.github.com/solnsumei/23105c6c1a7002593771912352e613cf file=myapp.dart %}

Finally we will be wrapping the children we need to receive updates from our FavoriteNotifier with ValueListenableBuilder and implement calls to update the UI accordingly.

{% gist https://gist.github.com/solnsumei/23105c6c1a7002593771912352e613cf file=mywidget2.dart %}

Running the app now will show the fruits in the favorites list icons as gold, while the others as grey, also the FAB button clears the list.

Now let's update the FavoriteCount widget to display the count of fruits in our favorite collection.

{% gist https://gist.github.com/solnsumei/23105c6c1a7002593771912352e613cf file=favorite_count.dart %}

finally, if you run the app now, you notice that both the icon color and the favorite count is updated when we tap on any of the fruit.

Here is the full code:

{% gist https://gist.github.com/solnsumei/23105c6c1a7002593771912352e613cf file=main.dart %}

You can run the final code on dartpad by clicking this link
[Code Editor](https://dartpad.dev/23105c6c1a7002593771912352e613cf)

## Conclusion

We simply constructed our own application state with flutter's built-in widgets, without the need for external libraries or rebuilding the entire widget tree with setState in a StatefulWidget.

You can explore more on your own and post your comments. If you have any question, please post it on the comments section and I'll be glad to answer. Happy coding!