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
任意位置声明共享状态
不再需要在你的 main.dart
和UI文件之间来回跳转。
将共享状态的代码放在它所属的位置上,无论是放在独立的package中还是放在需要它的Widget旁边,都不会丢失它的可测试性。
// A shared state that can be accessed by multiple
// objects at the same time
final countProvider = StateProvider((ref) => 0);
// 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');
}
}
最小粒度更新UI和重新计算状态
我们无需在 build
中对列表进行排序或过滤,也不必依赖高级的缓存机制。
使用 Provider
和 "families" 修饰符,那么它只会在你真正需要的时候才发起HTTP请求或整理你的列表。
final todosProvider = StateProvider<List<Todo>>((ref) => []);
final filterProvider = StateProvider<Filter>((ref) => Filter.all);
final filteredTodosProvider = Provider<List<Todo>>((ref) {
final todos = ref.watch(todosProvider);
switch (ref.watch(filterProvider)) {
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
使用provider不再导致错误的状态。恰当地使用provider,你可以始终获得一个可靠的结果。
这在异步操作中也是如此,Riverpod可以让你简洁地处理loading/error状态。
final configurationsProvider = FutureProvider<Configuration>((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 Riverpod's built-in support
// for error/loading states using "when":
return configs.when(
loading: () => const CircularProgressIndicator(),
error: (err, stack) => Text('Error $err'),
data: (configs) => Text('data: ${configs.host}'),
);
}
}
在DevTools中检查状态
你可以在Flutter的开发工具中一目了然地看到Riverpod的各种状态。
此外,一款功能更全面的状态检查工具正在开发中。
