ValueNotifier and ValueListenableBuilder in Flutter
In 2023, Flutter will be one of the most popular cross-platform frameworks for developing mobile apps. Flutter is Google’s UI toolkit for creating beautiful, natively compiled mobile, web, and desktop applications from a single codebase. In this post, we will take a deep dive into ValueNotifier and its related topics.
To understand the need for a ValueNotifier, we must first understand Flutter’s underlying architecture. We need to understand how the widgets are rebuilt when we call them.
What is ValueNotifier & ValueListenableBuilder in Flutter?
A ValueNotifier
is a simple class that allows you to expose a value and provide notifications when the value changes. It is often used in Flutter to hold and manage state.
The ValueNotifier
class extends the ChangeNotifier
class, which provides the ability to notify listeners when the value changes. To create a ValueNotifier
, you need to pass the initial value to the constructor. You can then expose the value using the value
property and update it using the value
setter.
Here is an example of how you might use a ValueNotifier
in a Flutter app:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final counter = ValueNotifier<int>(0);
void increment() {
counter.value++;
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Counter: ${counter.value}'),
RaisedButton(
onPressed: increment,
child: Text('Increment'),
),
],
),
),
),
);
}
}
In this example, the counter
variable is a ValueNotifier
that holds an integer value. The increment
method increments the value of the counter
and the Text
widget displays the current value.
The ValueNotifier
class is often used in conjunction with the ValueListenableBuilder
widget, which allows you to rebuild a widget tree whenever the value of the ValueNotifier
changes. This can be useful for optimizing the performance of your app by avoiding unnecessary rebuilds.
Here is an example of how you might use the ValueListenableBuilder
widget:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final counter = ValueNotifier<int>(0);
void increment() {
counter.value++;
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: ValueListenableBuilder(
valueListenable: counter,
builder: (context, value, child) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Counter: $value'),
RaisedButton(
onPressed: increment,
child: Text('Increment'),
),
],
);
},
),
),
),
);
}
}
In this example, the ValueListenableBuilder
widget is wrapped around the Column
widget that displays the counter value and the button. The valueListenable
property of the ValueListenableBuilder
is set to the counter
ValueNotifier
, and the builder
function is called whenever the value of the counter
changes. This allows the Column
widget to be rebuilt only when the value of the counter
changes, rather than being rebuilt on every frame.
Using a ValueNotifier
and a ValueListenableBuilder
can be a useful way to manage and optimize the state of your Flutter app. However, it is important to note that ValueNotifier
does not automatically trigger a rebuild of its dependents when the value changes. Instead, you must manually call the notifyListeners
method to trigger a rebuild.
In addition to ValueNotifier
, Flutter also provides the InheritedWidget
and Provider
classes, which can be used to manage and expose state in a Flutter app. It is important to choose the right tool for the job based on the requirements of your app.