| 分类 flutter  | 标签 Flutter  Riverpod 

title

引言

Riverpod 是 Provider 的继任者,由同一作者 Remi Rousselet 开发,解决了 Provider 对 BuildContext 的依赖、测试时需包装 ProviderScope、以及部分边缘场景下的问题。Riverpod 支持编译时安全(通过代码生成)、更好的测试性、无需 BuildContext 的依赖获取,Provider 可声明依赖关系并由 Riverpod 自动解析。flutter_riverpod 提供与 Flutter 的集成,ConsumerWidget、ConsumerStatefulWidget 通过 WidgetRef 访问 Provider。本文将介绍 Riverpod 的 Provider 类型、ref.watch 与 ref.read、与 Flutter 的集成以及最佳实践。

Riverpod 与 Provider 的对比

Provider 依赖 InheritedWidget,必须在 BuildContext 的子树中访问。Riverpod 的 Provider 是全局的,通过 ProviderScope 存储状态,ref 可在任何有 ProviderScope 祖先的地方使用。Riverpod 的 Provider 可依赖其他 Provider(通过 ref.watch 或 ref.read),形成依赖图,Riverpod 会按依赖顺序创建和更新。测试时只需 ProviderScope 并可 override Provider,无需包装 MaterialApp。

添加依赖

dependencies:
  flutter_riverpod: ^2.4.9
  riverpod_annotation: ^2.3.3

dev_dependencies:
  build_runner: ^2.4.7
  riverpod_generator: ^2.3.9

使用 riverpod_annotation 和 riverpod_generator 可通过注解生成 Provider,减少样板代码。

Provider 类型

  • Provider:不可变数据,创建后不变
  • StateProvider:简单可变状态,如计数器
  • FutureProvider:异步数据,如网络请求
  • StreamProvider:流数据,如 WebSocket
  • StateNotifierProvider:复杂可变状态,配合 StateNotifier
  • NotifierProvider(Riverpod 2.x):替代 StateNotifierProvider 的推荐方式
final counterProvider = StateProvider<int>((ref) => 0);
final userProvider = FutureProvider<User>((ref) => fetchUser());
final configProvider = Provider<Config>((ref) => Config());

使用

ConsumerWidget 的 build 方法接收 context 和 ref。ref.watch 监听 Provider,当 Provider 更新时重建 Widget;ref.read 仅读取当前值,不监听,适合在事件回调中使用。ref.listen 可监听并执行副作用(如显示 SnackBar),不重建。ProviderScope 需包裹根 Widget,通常放在 MaterialApp 外。

class MyWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);
    return Text('$count');
  }
}

// MaterialApp 需使用 ProviderScope
ProviderScope(child: MaterialApp(home: HomePage()))

总结

Riverpod 是现代化、类型安全的状态管理方案,适合中大型项目。掌握 Provider 类型选择、ref.watch 与 ref.read 的区别、以及依赖声明,可以构建清晰、可测试的状态管理架构。


上一篇     下一篇