With riverpod_generator
, I can use:
@riverpod
int foo(FooRef ref) => 0;
which is the equivalent of:
final fooProvider = Provider((ref) => 0);
But how can I do the same thing for other providers like FutureProvider
, StateProvider
, etc?
With riverpod_generator
, I can use:
@riverpod
int foo(FooRef ref) => 0;
which is the equivalent of:
final fooProvider = Provider((ref) => 0);
But how can I do the same thing for other providers like FutureProvider
, StateProvider
, etc?
With code generation, you can use simplify your providers declaration. There are mainly five providers and you can see how to generate the equivalent code for each of them.
Provider
:The equivalent of
final fooProvider = Provider((ref) => 0);
is
@riverpod
int foo(FooRef ref) => 0;
FutureProvider
:The equivalent of
final fooProvider = FutureProvider((ref) async {
return 0;
});
is
@riverpod
Future<int> foo(FooRef ref) async {
return 0;
}
StateProvider
:The equivalent of
final fooProvider = StateProvider((ref) => 0);
is
@riverpod
class Foo extends _$Foo {
@override
int build() => 0;
}
First, install riverpod, exemple for flutter (because you can use riverpod only for Dart) :
flutter pub add flutter_riverpod dev:custom_lint dev:riverpod_lint riverpod_annotation dev:build_runner dev:riverpod_generator
'dev:custom_lint' and 'dev:riverpod_lint' are for code quality.
In your main.dart, add ProviderScode
/// For providers to work, you must add ProviderScope at the root of your Flutter applications:
///source: https://riverpod.dev/docs/concepts/providers
void main() {
runApp(ProviderScope(child: MyApp()));
}
Create a counter class for example (counter.dart)
import 'package:flutter/material.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
//add this line (standard configuration, you will got an error in vscode before you launch riverpod_generator because the file not existe yet)
part 'counter.g.dart';
// '@riverpod' annotation will be use by riverpod_generator
// to generate 'counterProvider' automatically
@riverpod
class Counter extends _$Counter {
@override
int build() {
// initial value de type int
return 0;
}
void increment() {
state++;
}
void decrement() {
state--;
}
}
Run riverpod_generator (it will become in background, and refresh after code modification to rebuild counter.g.dart (provider is inside this file) automatically
flutter pub run build_runner watch -d
And for the UI
//Extends ConsumerWidget to be able to access the counterProvider via ref.watch
class MyHomePage extends ConsumerWidget {
class MyHomePage extends ConsumerWidget {
const MyHomePage({super.key, required String title});
@override
// With ref you can access the provider
Widget build(BuildContext context, WidgetRef ref) {
//observe modification of provider
final counter = ref.watch(counterProvider);
//To access previous and current value, you can use listen
ref.listen<int>(counterProvider, (previous, next) {
print('prec : $previous | current valeur : $next');
}, onError: (error, stackTrace) {});
return Scaffold(
appBar:
AppBar(title: const Text('riverpod + riverpod_generator example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
//couter will update in real time !
Text('$counter'),
])),
floatingActionButton:
Row(mainAxisAlignment: MainAxisAlignment.end, children: [
FloatingActionButton(
onPressed: () {
//don't use ref.watch here (official documentation)
//ref.read(counterProvider.notifier).state--;
//use ref.read after a user action (click on a button for example)
ref.read(counterProvider.notifier).decrement();
},
tooltip: 'Decrement',
child: const Icon(Icons.remove)),
const SizedBox(width: 50),
FloatingActionButton(
onPressed: () {
//ref.read(counterProvider.notifier).state++;
ref.read(counterProvider.notifier).increment();
},
tooltip: 'Increment',
child: const Icon(Icons.add))
]));
}
}}