Riverpod code generation (@riverpod)
Riverpod can be written two ways: by hand (you declare the provider yourself) and with code generation (you write a function/class with the @riverpod annotation and the provider is generated).
Setup, per the official docs:
- Dependencies:
flutter_riverpodandriverpod_annotation. - Dev dependencies:
riverpod_generatorandbuild_runner. - Generation:
dart run build_runner watch -d. - The file needs a
part 'file.g.dart';directive at the top. riverpod_lintis not part of the core installation — it is an optional lint tool configured throughanalysis_options.yaml.
The annotation picks the provider type for you: no manual choice between Provider, FutureProvider and StreamProvider — the function's signature decides. For a function named myFunction, a myFunctionProvider is generated.
// ---------- Əl ilə ----------
final todoRepositoryProvider = Provider<TodoRepository>((ref) {
return TodoRepository(ref.watch(apiClientProvider));
});
final todosProvider =
AsyncNotifierProvider<TodosNotifier, List<Todo>>(TodosNotifier.new);
// family: yalnız bir pozisional arqument
final productProvider = FutureProvider.family<Product, String>(
(ref, id) => ref.watch(catalogRepositoryProvider).fetch(id),
);
// ---------- Codegen ----------
// fayl: todos.dart
part 'todos.g.dart';
@riverpod
TodoRepository todoRepository(Ref ref) {
return TodoRepository(ref.watch(apiClientProvider));
}
@riverpod
class Todos extends _$Todos {
@override
Future<List<Todo>> build() => ref.watch(todoRepositoryProvider).fetchAll();
Future<void> add(String title) async { /* ... */ }
}
// Parametrlər adi funksiya arqumentləridir: adlı, opsional, default dəyərli.
@riverpod
Future<List<Product>> search(
Ref ref, {
required String query,
int page = 1,
}) {
return ref.watch(catalogRepositoryProvider).search(query, page: page);
}
// İstifadə: ref.watch(searchProvider(query: 'telefon'));The same provider: by hand and with codegen.
| Criterion | With codegen | Without codegen |
|---|---|---|
| Choosing the provider type | Automatic — inferred from the signature | Chosen by hand |
| Parameters (family) | Named, optional, defaulted — unrestricted | One positional argument |
| autoDispose | On by default; disabled with `@Riverpod(keepAlive: true)` | Specified explicitly |
| Hot reload | Per the docs, stateful hot reload of Riverpod code is supported | Ordinary Flutter hot reload |
| Build time | Grows — the docs note codegen "is still fairly slow" | No extra step |
The docs' honest recommendation: code generation brings many benefits but is still fairly slow; so it makes sense to adopt when you already run codegen for other packages (freezed, json_serializable), rather than introducing it on its own. A good citation for a balanced position in an interview.
📚 Sources and documentation
- About code generationofficialriverpod.dev
The benefits, the "still fairly slow" caveat and when to adopt it.
- Riverpod: installationofficialriverpod.dev
The package list, the build_runner watch -d command and the part directive.
- package:riverpod_generatorofficialpub.dev
- package:riverpod_lintofficialpub.dev
The optional lint package that enforces part of the DO/DON'T rules in static analysis.