While you may not have much space left for State Management Solutions, I am here to introduce another one π€.StateNotifier is an extension to the ValueNotifier Class. It fixes the pre-existing issues persisting in ValueNotifier which we will discuss ahead. StateNotifier is mostly used along with State Management solutions like Provider or Riverpod. In this post, we will discuss how to use StateNotifier in Flutter along with the need for StateNotifier.
Pre-requisitives π
- State in Flutter, in simple terms, is a particular condition that our app is in at a specific time.
- ValueNotifier, in short, is a simple State Management Solution provided by Flutter natively.
Need for StateNotifier? π«
You may have used ChangeNotifier or ValueNotifier along with Provider and it does work fine. While we may not end up with any fatal errors while using them, there are some issues with these implementations.
- ChangeNotifier and ValueNotifiers are mutable, i.e anybody from outside the class can change the State of the notifier. This behavior is not expected as we expect the interaction with the data via functions.
- We need to manually call
notifyListeners()
while using ChangeNotifier.
Let’s see the advantages of StateNotifier:
- Immutable in nature.
- Compares old and new states and notifies listeners automatically.
- Single Data Modification Point.
Now that we have enough reasons to use StateNotifier let’s dive into StateNotifier.
StateNotifier in Flutter β½
As we discussed StateNotifier is an extension of ValueNotifier. Like ValueNotifier it also stores one value and notifies of changes, just that StateNotifier is immutable while others are not. Also, StateNotifier is independent of flutter, and thus can be used in your Dart projects as well.
Now without further due let’s add the needed dependencies to use StateNotifier:
// # pubspec.yaml
dependencies:
state_notifier:
flutter_state_notifier:
NOTE: In this post, we will not discuss implementation with Riverpod or Provider. We will simply use the Widgets provided in flutter_state_notifier
package to consume the StateNotifier.
Creating our first StateNotifier π₯’
As a simple example let’s create a StateNotifier for our traditional Counter application. We just need to simply extend StateNotifier in place of ValueNotifier, and we have our StateNotifier class ready.

Like we use “value” inside the ValueNotifier class to get the current state, Similarly we use the “state” keyword to access the current state of the StateNotifier class.
// # lib/data/state_counter.dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
class StateCounter extends StateNotifier<int> {
StateCounter() : super(0);
// Add all modification functions here
// as we can't modify the data from outside
void increment() {
state++;
}
void decrement() {
state--;
}
}
Similar to ValueNotifier here also we have to pass the initialValue
to the super constructor. Now that we have our StateCounter
ready, let’s see how to consume it.
Consuming StateNotifier in Flutter π
As we discussed we won’t be using Provider or Riverpod in this tutorial. Thus to simply access our StateNotifier we will declare it as a global variable so that we can access a single instance across multiple pages.
Note that, declaring global variables is not a good approach, as we should manually dispose of our objects when not in use. However, global variables get disposed of when our application is exited. To avoid this issue we use StateNotifier in combination with Provider or RiverPod.
Thus, here we are using global variables for the sake of simplicity:
// # lib/data/state_counter.dart
class StateCounter extends StateNotifier<int>{...}
// Singleton Global Instance
final StateCounter myCounter = StateCounter();
To Consume our StateCounter
we will use StateNotifierBuilder
which is provided by flutter_state_counter
package.
StateNotifierBuilder in Flutter πͺ
StateNotifierBuilder is similar to ValueNotifierBuilder
for ValueNotifier. It takes a StateNotifier as a listener and rebuilds the widget tree on value change. The constructor of StateNotifierBuilder is:
const StateNotifierBuilder({
Key? key,
required this.builder,
required this.stateNotifier,
this.child,
})
We simply pass our StateNotifier in the stateNotifier
parameter. In the builder
parameter we get the current value of our StateNotifier. We can easily comprehend the StateNotifierBuilder through our code.
// # lib/pages/home_page.dart
import 'package:flutter/material.dart';
import 'package:flutter_state_notifier/flutter_state_notifier.dart';
import 'package:state_notifier_example/data/state_counter.dart';
import 'package:state_notifier_example/pages/next_page.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("State Notifier Demo"),
),
floatingActionButton: FloatingActionButton(
// 1 ~
onPressed: () => myCounter.increment(),
child: const Icon(Icons.add),
),
body: StateNotifierBuilder(
stateNotifier: myCounter,
builder: (context, value, child) {
// 2 ~
return Center(
child: Text(value.toString()),
);
},
),
);
}
}
Code Explanation:
- We declared our StateNotifier global by the name
myCounter
so we can easily use theincrement()
method on the instance. - Using our
StateNotifierBuilder
we specifically only rebuild the Text as that is the only widget that changes in case our value changes.
Conclusion π₯
It is not about StateNotifier VS ChangeNotifier or StateNotifier VS ValueNotifier. The StateNotifier does not replace ChangeNotifier and ValueNotifier, however, it’s just an addition to the list of State Management Solutions. The upside with StateNotifier is that it is inbuilt in the Riverpod. In a normal project, it makes no sense to me to add dependencies to achieve something similar to ValueNotifier. Thus, we will extend this post with a post on StateNotifier with Riverpod in Flutter.
If you have any queries you can comment below and I will be happy to help you. Following you must check these posts:
- Testing in Flutter
- Null Safety in Dart, Flutter Essentials
- GetX in Flutter
- Streams in Flutter, Simplified
- App Lifecycle in Flutter
If you are new to Flutter, check my post on how to install flutter on windows?