Riverpod generator
Welcome!
This project is a side package for Riverpod, meant to offer a different syntax for defining "providers" by relying on code generation.
Without any delay, here is how you
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:dio/dio.dart';
part 'my_file.g.dart';
// Using riverpod_generator, we define Providers by annotating functions with @riverpod.
// In this example, riverpod_generator will use this function and generate a matching "fetchProductProvider".
// The following example would be the equivalent of a "FutureProvider.autoDispose.family"
@riverpod
Future<List<Product>> fetchProducts(Ref ref, {required int page, int limit = 50}) async {
final dio = Dio();
final response = await dio.get('https://my-api/products?page=$page&limit=$limit');
final json = response.data! as List;
return json.map((item) => Product.fromJson(item)).toList();
}
// Now that we defined a provider, we can then listen to it inside widgets as usual.
Consumer(
builder: (context, ref, child) {
AsyncValue<List<Product>> products = ref.watch(fetchProductProvider(page: 1));
// Since our provider is async, we need to handle loading/error states
return products.when(
loading: () => CircularProgressIndicator(),
error: (err, stack) => Text('error: $err'),
data: (products) {
return ListView(
children: [
for (final product in products)
Text(product.name),
],
);
},
);
},
);
This new syntax has all the power of Riverpod, but also:
- solves the problem of knowing "What provider should I use?".
With this new syntax, there is no such thing asProvider
vsFutureProvider
vs ... - enables stateful hot-reload for providers.
When modifying the source code of a provider, on hot-reload Riverpod will re-execute that provider and only that provider. - fixes various flaws in the existing syntax.
For example, when passing parameters to providers by using family, we are limited to a single positional parameter. But with this project, we can pass multiple parameters, and use all the features of function parameters. Including named parameters, optional parameters, default values, ...
This project is entirely optional. But if you don't mind code generation, definitely consider using it over the default Riverpod syntax.
Getting started
Installing riverpod_generator
To install riverpod_generator, edit your pubspec.yaml
and add the following:
dependencies:
# or flutter_riverpod/hooks_riverpod as per https://riverpod.dev/docs/getting_started
riverpod:
# the annotation package containing @riverpod
riverpod_annotation:
dev_dependencies:
# a tool for running code generators
build_runner:
# the code generator
riverpod_generator:
Don't forget to run flutter pub get
/ dart pub get
.
Starting the code generator
To start the code generator, run the following command:
dart run build_runner watch
Defining our first "provider"
Now that we have installed riverpod_generator and started the code generator, we can start defining providers.
Let's make a hello world using riverpod_generator:
// main.dart
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter/material.dart';
part 'main.g.dart';
// Providers are defined by annotating a function with @riverpod
@riverpod
String label(Ref ref) => 'Hello world';
void main() {
runApp(ProviderScope(child: Home()));
}
class Home extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
home: Scaffold(
// We can then listen to the generated provider in our widgets.
body: Text(ref.watch(labelProvider)),
),
);
}
}
Global configuration
You can change provider name suffix in the build.yaml file:
targets:
$default:
builders:
riverpod_generator:
options:
# Could be changed to "my", such that riverpod_generator
# would generate "myCountProvider" instead of "countProvider"
provider_name_prefix: "" # (default)
# Similar to provider_name_prefix, this is an option for renaming
# providers with parameters ("families").
# This takes precedence over provider_name_prefix.
provider_family_name_prefix: "" # (default)
# Could be changed to "Pod", such that riverpod_generator
# would generate "countPod" instead of "countProvider"
provider_name_suffix: "Provider" # (default)
# Similar to provider_name_suffix, this is an option for renaming
# providers with parameters ("families").
# This takes precedence over provider_name_suffix.
provider_family_name_suffix: "Provider" # (default)