SuperAPI AI 工具集

riverpod-codegen-and-hooks

编程与开发

查看项目

更新于 10-16 02:25

技能介绍

用途

本技能介绍 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 细节参见官方文档。