用途
本技能介绍 Riverpod 的两个可选特性:代码生成(code generation)与 Hooks,以及二者结合使用的方式。
代码生成
代码生成在 Riverpod 中是可选的。它会改变定义 provider 的语法:你编写带注解的函数或类,生成器负责产出 provider。如果你已经在使用代码生成(例如 Freezed、json_serializable),可以采用它;否则额外的构建步骤可能并不划算。相关设置(build_runner、riverpod_generator)参见 riverpod-getting-started。
优势
- 语法更清晰:无需手动指定 provider 类型(Provider、FutureProvider 等),Riverpod 会自动推断。
- 参数:可使用任意参数(命名、可选、默认值),而不再局限于单个 family 参数。
- Riverpod 代码支持有状态热重载。
- 通过生成的元数据获得更好的调试体验。
语法
函数式 provider(同步):
@riverpod
String example(Ref ref) {
return 'foo';
}
基于类的 provider(同步,可添加方法用于副作用):
@riverpod
class Example extends _$Example {
@override
String build() => 'foo';
// 添加方法以修改状态
}
异步:使用 Future/FutureOr/Stream;异步函数会自动获得 AsyncValue 以及加载/错误处理。自动释放(Auto-dispose):在代码生成下默认开启。可通过 @Riverpod(keepAlive: true) 禁用。
@riverpod
String example1(Ref ref) => 'foo';
@Riverpod(keepAlive: true)
String example2(Ref ref) => 'foo';
参数:为函数添加参数(一致的 == 为必需):
@riverpod
Future<User> fetchUser(Ref ref, {required int userId}) async {
final json = await http.get('api/user/$userId');
return User.fromJson(json);
}
手动等价写法为 FutureProvider.autoDispose.family<User, int>(...)。相关概念参见 riverpod-providers 与 riverpod-family。
Hooks
Hooks 来自 flutter_hooks(与 Riverpod 相互独立)。它们用于组件本地状态(例如 TextEditingController、AnimationController),可以替代 StatefulWidget 或减少 builder 嵌套。仅在你确实想使用 hooks 时才使用;它们并非 Riverpod 的必需项。新手应避免一开始就使用 hooks。
同时使用 hooks 与 Riverpod
你需要同时引入 flutter_hooks 和 hooks_riverpod。然后可选择:
选项 1:HookConsumerWidget —— 一个同时支持 hooks 与 ref 的基类:
class Example extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final counter = useState(0);
final value = ref.watch(myProvider);
return Text('Hello $counter $value');
}
}
选项 2:HookConsumer —— 结合 HookBuilder + Consumer 的 builder(仅在嵌套使用时适用于 flutter_riverpod;hooks_riverpod 提供 HookConsumer):
return HookConsumer(
builder: (context, ref, child) {
final counter = useState(0);
final value = ref.watch(myProvider);
return Text('Hello $counter $value');
},
);
选项 3:嵌套 Consumer 与 HookBuilder(无需 hooks_riverpod)。
Hooks 规则
- 仅在继承 HookWidget(或 HookConsumerWidget)的组件的 build 方法中使用 hooks。
- 不要有条件地或在循环中使用 hooks;调用顺序必须保持稳定。
组件中的 Ref 参见 riverpod-consumers,完整的代码生成/hooks 细节参见官方文档。