Declarative programming
Write business logic in a manner similar to Stateless widgets.
Have your
network requests to automatically recompute when necessary and make
your logic easily reusable/composable/maintainable.
Easily implement common UI patterns
Using Riverpod, common yet complex UI patterns such as "pull to refresh"/ "search as we type"/etc... are only a few lines of code away.
Tooling ready
Riverpod enhances the compiler by having common mistakes be a compilation-error. It also provides custom lint rules and refactoring options. It even has a command line for generating docs.
Features
- ✅ Declarative programming
- ✅ Native network requests support
- ✅ Automatic loading/error handling
- ✅ Compile safety
- ✅ Type-safe query parameters
- ✅ Test ready
- ✅ Work in plain Dart (servers/CLI/...)
- ✅ Easily combinable states
- ✅ Built-in support for pull-to-refresh
- ✅ Custom lint rules
- ✅ Built-in refactorings
- ✅ Hot-reload support
- ✅ Logging
- ✅ Websocket support
- ✅ Documentation generator
Gemeinsamen Zustand von überall aus deklarieren
Du musst nicht mehr zwischen deiner main.dart
und deinen UI Dateien
hin- und herspringen.
Platziere den Code deines gemeinsamen Zustands dort, wo er hingehört, sei
es in einem separaten Paket oder direkt neben dem Widget, das
ihn benötigt, ohne dass die Testbarkeit verloren geht.
// A shared state that can be accessed by multiple widgets at the same time.
class Count extends _$Count {
int build() => 0;
void increment() => state++;
}
// Consumes the shared state and rebuild when it changes
class Title extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(countProvider);
return Text('$count');
}
}
Neuberechnung von Zuständen/Neuaufbau der Benutzeroberfläche nur bei Bedarf
Listen müssen nicht mehr in der build
Methode sortiert/gefiltert
werden oder auf erweiterte Cache-Mechanismen zurückgreifen.
Mit Provider
und "families" sortierst du deine Liste oder machst HTTP
Requests nur noch, wenn du es wirklich brauchst.
List<Todo> filteredTodos(FilteredTodosRef ref) {
// Providers can consume other providers using the "ref" object.
// With ref.watch, providers will automatically update if the watched values changes.
final List<Todo> todos = ref.watch(todosProvider);
final Filter filter = ref.watch(filterProvider);
switch (filter) {
case Filter.all:
return todos;
case Filter.completed:
return todos.where((todo) => todo.completed).toList();
case Filter.uncompleted:
return todos.where((todo) => !todo.completed).toList();
}
}
Simplify day-to-day work with refactors
Riverpod offers various refactors, such as "Wrap widget in a Consumer" and many more. See the list of refactorings.
Keep your code maintainable with lint rules
New lint-rules specific to Riverpod are implemented and more are continuously added. This ensures your code stays in the best conditions. See the list of lint rules.
Provider sicher lesen
Das Lesen eines Providers wird niemals zu einem bad state führen. Wenn
der benötigte Code zum Auslesen eines Providers geschrieben werden kann, erhält man
einen validen Wert.
Das gilt auch für asynchron geladene Werte. Im Gegensatz
zu Providern erlaubt Riverpod eine saubere Handhabung
von Lade-/Fehlerfällen.
Future<Configuration> configurations(ConfigurationsRef ref) async {
final uri = Uri.parse('configs.json');
final rawJson = await File.fromUri(uri).readAsString();
return Configuration.fromJson(json.decode(rawJson));
}
class Example extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final configs = ref.watch(configurationsProvider);
// Use pattern matching to safely handle loading/error states
return switch (configs) {
AsyncData(:final value) => Text('data: ${value.host}'),
AsyncError(:final error) => Text('error: $error'),
_ => const CircularProgressIndicator(),
};
}
}
Überprüfe deinen Zustand im Devtool
Durch die Verwendung von Riverpod ist dein Zustand direkt im Devtool von Flutter sichtbar.
Darüber hinaus ist ein vollwertiger State-Inspector in Arbeit.