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 mobile, web, and desktop from a single codebase. In this post, we will dive deep 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 calling.
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.

While using setState
is appropriate in most situations. If not used properly, there can be some issues with setState
:
- Tight coupling between frontend and backend.
- 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 listen 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 of 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 of 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 Scaffold, AppBar, 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:
- Complete Guide to StateNotifier in Flutter
- State Management using RiverPod in Flutter
- Testing in Flutter
- Null Safety in Dart, Flutter Essentials
- Streams in Flutter, Simplified
- App Lifecycle in Flutter
If you are new to Flutter, check my post on how to install flutter on windows?
Thank you, Fantastic artical , This was really helpful for me.
easy to understand. Great job ! keep continue.