Flutter: Value Notifier
Value notifier is a simple class that extends ChangeNotifier and allows you to notify listeners when the value changes.
Example: we will do a simple counter that increments when press a button, our state will be provided by a value notifier.
To start we need 3 files:
- notifier.dart: will be our value notifier
- increment_button.dart: will be our component that will increment the counter
- decrement_button.dart: will be our component that will decrement the counter
//notifier.dart
import 'package:flutter/material.dart';
class _Counter {
ValueNotifier<int> count = ValueNotifier<int>(0);
increment() {
count.value++;
}
decrement() {
count.value--;
}
}
var counter = _Counter();
Here we create a class called _Counter, that class exposes a ValueNotifier called count
and two methods increment and decrement that will increment and decrement the value of count.
Now we will create our two buttons.
//increment_button.dart
import 'package:flutter/material.dart';
import 'controller.dart';
class IncrementButton extends StatelessWidget {
const IncrementButton({super.key});
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: counter.count,
builder: (context, value, child) {
return ElevatedButton(
onPressed: () {
counter.increment();
},
child: SizedBox(
width: 120,
child: Center(
child: Text('Increment: $value'),
),
),
);
},
);
}
}
//decrement_button.dart
import 'package:flutter/material.dart';
import 'controller.dart';
class DecrementButton extends StatelessWidget {
const DecrementButton({super.key});
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: counter.count,
builder: (context, value, child) {
return ElevatedButton(
onPressed: () {
counter.decrement();
},
child: SizedBox(
width: 120,
child: Center(
child: Text('Decrement: $value'),
),
),
);
},
);
}
}
In these two components we can observe the usage of ValueListenableBuilder.
That widget will listen to the changes of ValueNotifier and rebuild the
widget when the value changes.
Now we can use our components in our page.
//page.dart
import 'package:flutter/material.dart';
import 'decrement_component.dart';
import 'increment_component.dart';
class Page extends StatelessWidget {
const Page({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IncrementButton(),
SizedBox(height: 20),
DecrementButton(),
],
),
),
);
}
}
The main advantage of using ValueNotifier is that we can use it in any widget and share the same state.
👉 Check the full code here.