Skip to main content

ProviderObserver

caution

The content of this page may be outdated.
It will be updated in the future, but for now you may want to refer to the content in the top of the sidebar instead (introduction/essentials/case-studies/...)

ProviderObserver listens to the changes of a ProviderContainer.

To use it, extend the class ProviderObserver and override the method you want to use.

ProviderObserver has three methods :

  • didAddProvider is called every time a provider was initialized, and the value exposed is value.
  • didDisposeProvider is called every time a provider was disposed.
  • didUpdateProvider is called every time by providers when they emit a notification.

Usage :

A simple use case for ProviderObserver is to log the changes in providers by overriding the didUpdateProvider method.


// A Counter example implemented with riverpod with Logger

class Logger extends ProviderObserver {

void didUpdateProvider(
ProviderBase<Object?> provider,
Object? previousValue,
Object? newValue,
ProviderContainer container,
) {
print('''
{
"provider": "${provider.name ?? provider.runtimeType}",
"newValue": "$newValue"
}''');
}
}

void main() {
runApp(
// Adding ProviderScope enables Riverpod for the entire project
// Adding our Logger to the list of observers
ProviderScope(observers: [Logger()], child: const MyApp()),
);
}

class MyApp extends StatelessWidget {
const MyApp({super.key});


Widget build(BuildContext context) {
return MaterialApp(home: Home());
}
}

final counterProvider = StateProvider((ref) => 0, name: 'counter');

class Home extends ConsumerWidget {

Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);

return Scaffold(
appBar: AppBar(title: const Text('Counter example')),
body: Center(
child: Text('$count'),
),
floatingActionButton: FloatingActionButton(
onPressed: () => ref.read(counterProvider.notifier).state++,
child: const Icon(Icons.add),
),
);
}
}

Now, every time the value of our provider is updated, the logger will log it:

I/flutter (16783): {
I/flutter (16783): "provider": "counter",
I/flutter (16783): "newValue": "1"
I/flutter (16783): }
:

For states that are mutable such as StateController (the state of StateProvider.state) and ChangeNotifier the previousValue and newValue will be the same

since they reference the same StateController / ChangeNotifier.