Complete Guide to ValueNotifier in Flutter

Flutter is one of the most popular cross-platform frameworks for mobile apps development in 2020. Flutter is Google’s UI toolkit for building beautiful, natively compiled applications for mobileweb, and desktop from a single codebase. In this post, we will deep dive into ValueNotifier along with its corresponding topics.

Firstly, to understand the need for a ValueNotifier we need to understand the underlying architecture of Flutter. We need to have an understanding of how the widgets are rebuilt when call.

State in Flutter

In Flutter, everything is a widget. Flutter maintains the current state of the app at every given time, so anytime we update the User Interface we say that we are updating the state.

Flutter has its own state management system, the popular setState function in Stateful Widget that executes the build method whenever called. By default the program follows its lifecycle but when setState is invoked the program re-runs the build method and rebuilds the widget tree.

This image shows the state management in Flutter. A subpart of the ValueNotifier in Flutter post.
Flutter State Equation

While using setState is appropriate in most situations. If not used properly, there can be some issues with setState:

  1. Tight coupling between frontend and backend.
  2. It rebuilds the whole widget again, which can be expensive and time taking.

That’s why today we are going to look at another method to update state using ValueNotifier. It is used in cases where we want to implement selective rebuilding, which is the case in most application designs. If you are interested to know more about State you can check my post on State Management in Flutter.

Intro to ValueNotifier in Flutter

ValueNotifier is a special type of class that extends a ChangeNotifier. ValueNotifier is native to Flutter itself, it provides individual element reactivity. Flutter also has a widget by default, using which we can listen to the ValueNotifier called ValueListenableBuilder. It can also be listened using AnimationBuilder since it is Listenable.

Think of ValueNotifier as a stream of data which holds to a value. We provide it a value and every listener receives a notification of the value change.

We can create a ValueNotifier of any type int, bool, list, or any custom data type. You can create a ValueNotifier object like this:

ValueNotifier<int> counter = ValueNotifier<int>(0);

We can update the value like this:

counter.value = counter.value++;
//OR
counter.value++;

In addition, we can listen to the ValueNotifier like this:

counter.addListener((){
   print(counter.value); 
});

If we want to listen to the value in a widget, we use the ValueListenableBuilder widget, which out of the box takes care of removing the subscription once out of view. Thus, when using ValueListenableBuilder we don’t manually need to add and remove listeners, it automatically does that for us.

Remove Value Notifier Listener in Flutter

If we are listening to a ValueNotifier manually, and we do not dispose it because it’s needed somewhere in the application. We can manually remove a listener from the ValueNotifier when not in use on the current page, using the removeListener function.

ValueNotifier<int> valueNotifier = ValueNotifier(0);

void removeDemo() {
  valueNotifier.removeListener(doTaskWhenNotified);
}

void addDemo(){
  valueNotifier.addListener(doTaskWhenNotified);
}

void doTaskWhenNotified() {
  print(valueNotifier.value);
}

Disposing ValueNotifier in Flutter

It is a good practice to dispose the Value Notifier when no longer in use, otherwise it may lead to memory leaks. The dispose method on the notifier will release any subscribed listener.

 @override
 void dispose() {
    counter.dispose();
    super.dispose();
 }

What is ValueListenableBuilder?

There are many types of builders in Flutter like StreamBuilder, AnimatedBuilder, FutureBuilder, etc. Their first name suggests what type of object they consume. The ValueListenableBuilder consumes the ValueNotifier object. The builder method is executed every time we receive a value update. The ValueListenableBuilder automatically removes the listener internally when we route to another page.

const ValueListenableBuilder({
    @required this.valueListenable,
    @required this.builder,
    this.child,
  })

This is the constructor of ValueListenableBuilder. Here, valueListenable is the ValueNotifier to listen. The builder function receives 3 parameters (BuildContext context, dynamic value, Widget child). The value is the data received from the valueNotifier provided. It is possible to use the child parameter. We use it for optimization if the child is expensive to build and doesn’t depend upon the value from the notifier.

Counter App using Value Notifier in Flutter

The counter app using ValueNotifer and ValueListenableBuilder looks like this. Note how no setState is being used, and we rebuilt only the Text section in case of the value changes.

This approach, even if the code is a little longer, is more efficient than the traditional setState one. The only part that needs to be repainted is the Text widget. For this example, there is no need to rebuild the whole widget, the ScaffoldAppBar, or even the FloatingActionButton that triggers the change.

BONUS! Your own ValueNotifier in Flutter

You can easily extend the ValueNotifier class and make your custom ValueNotifier with custom functions. The value datatype should be specified while extending it. The class will itself contain a property value that specifies the current value of your custom ValueNotifier class.

class CounterNotifier extends ValueNotifier<int> {
  CounterNotifier({int? value}) : super(value ?? 0);

  void increment() {
    value++;
  }

  void decrement() {
    value--;
  }
}

Complete Counter Code with custom ValueNotifier:

To read more about Custom ValueNotifier you can check my recent post.

Conclusions:

Flutter has many state management techniques. Be it using advanced packages like GetX, BLoC, RiverPod, Provider, or just setState. The ValueNotifier is a native feature in Flutter and ValueListenableBuilder provides optimized rebuilding of a particular segment. If you want to notify some segment of the app about a value change remember a native solution, ValueNotifer.

Since Flutter can render a tree of widgets quickly, both solutions are correct. However, just as a developer, I believe in optimization and clean code. Which the various builders help us do. (eg: StreamBuilder, FutureBuilder, ValueListenableBuilder, and others).

If you have any queries you can comment below and I will be happy to help you. Following you must check these posts:

If you are new to Flutter, check my post on how to install flutter on windows?

Leave a Reply

Your email address will not be published.

Previous Post

Flutter: How to create Code Snippets?

Next Post
FutureBuilder in Flutter

Complete Guide to FutureBuilder in Flutter

Related Posts