ValueNotifier and setState

I’m Emmanuel David Tuksa, a Software Engineer passionate about building impactful digital experiences and solving real-world problems through technology. With a strong foundation in software engineering and a focus on mobile and web solutions, I’m driven to craft user-centric products that scale and delight. I continuously seek opportunities to learn, contribute to open-source, and push the boundaries of what technology can achieve. Whether it’s leading teams, optimizing workflows, or building something from scratch, my goal is simple: create meaningful software that empowers users and teams alike. Let’s build something great together.

Introduction
In flutter, we know that everything is a widget. The widgets can be divided into two; Stateless Widgets and Stateful Widgets. While the Stateless widget cannot be modified or changed once it has been built due to the fact that it does not have any internal state and must be initialised again to reflect changes, the Stateful widget can be modified during it’s life-cycle without having to be reinitialised again.
Stateful widgets can be rebuilt by calling **setState**. This callback notifies the framework that the internal state of the object has been changed. However, it is not best practice to rebuild the entire widget and just rebuilding the what we want to update is a more efficient way of going about things. In this article, we would be looking at how to update parts of the UI without having to call **setState** and rebuild the entire widget tree.
ChangeNotifier is a simple class which provides change notification to its listeners. ValueNotifier is a a special type of class that extends a ChangeNotifier. When value is replaced with something that is not equal to the old value, this class notifies its listeners. Changes to the value can be listened to by either **ValueListenableBuilder** or **AnimatedBuilder** . Using a ValueNotifier and ValueListenableBuilder eliminates unnecessary rebuilds of the widget as the only update that’ll occur would be for the ValueListenableBuilder.
Below is an example of how to use a substitute setState with the ChangeNotifier.
Create a New Flutter Project
Open your terminal, navigate to the folder you’ll like to create a new project and run the following command
flutter create ***project_name***
Your main.dart file should look somewhat like the code below:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
This uses setState to update the value of counter, thereby rebuilding the widget each time the value is changed. We’ll look at a different approach to this using the ValueNotifier .
Change
_counterType
Changeint _counter = 0;
tofinal _counter = ValueNotifier<int>(0);
Now _counter is a type of ValueNotifier.
Edit
_incrementCountermethod
Replace the content of the _incrementCounter with the code below
void _incrementCounter() {
_counter.value++;
}
Listen to Changes
Finally, we would wrap the text widget with the **ValueListenableBuilder** to listen to the changes on _counter .
Replace:
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
With:
ValueListenableBuilder(
valueListenable: _counter,
builder: (context, value, _) {
return Text(
'$value',
style: Theme.of(context).textTheme.headline4,
);
}
),
With this new method of updated _counter , whenever there is a change to the value of _counter only the **ValueListenableBuilder** is updated, hereby avoiding any unnecessary rebuild. This method would be efficient for more complex applications and improves the performance of your flutter application.
Conclusion
This draws us to the end of our short journey on ValueNotifier and setState flutter, I hope it has been really helpful so far. If you have any more questions or want to engage feel free to connect with me on Twitter or LinkedIn. Do appreciate the article with some claps and comments.
If you want the complete code, here is a link to the github repository of the project.

