SuperAPI AI 工具集

riverpod-providers

编程与开发

查看项目

更新于 10-16 02:25

技能介绍

用途

Provider 是 Riverpod 的核心特性:它们是带记忆(memoized)的函数,会缓存自己的结果,并允许多个 Widget(或其他 Provider)访问同一个值。Provider 以顶层 final 变量声明。状态存放在 ProviderContainer(Flutter 中为 ProviderScope)中,而不是存放在 Provider 本身。

Provider 变体

按返回类型分为三类:同步、Future、Stream。

  • 不可修改(Unmodifiable):Provider、FutureProvider、StreamProvider
  • 可修改(Modifiable):NotifierProvider、AsyncNotifierProvider、StreamNotifierProvider

选择规则:

  • 同步 vs Future vs Stream:与函数的返回类型匹配(int、Future<T>、Stream<T>)。
  • 不可修改:Widget 只读取值。用于计算或获取的数据。
  • 可修改:暴露一个带 build() 方法和自定义方法的 Notifier;Widget 通过 ref.read(provider.notifier).someMethod() 调用。当 UI 需要更新状态时使用。

根据你想返回的内容选择类型,Provider 类型自然随之确定。FutureProvider / AsyncNotifierProvider 是最常用的。

创建 Provider(不可修改 / 函数式)

手动方式:

final userProvider = FutureProvider<User>((ref) async {
  final response = await http.get('https://api.example.com/user/123');
  return User.fromJson(response.body);
});

代码生成:用 @riverpod 注解一个顶层函数。第一个参数必须是 Ref ref。生成的 Provider 名称为 functionNameProvider。

@riverpod
Future<User> user(Ref ref) async {
  final response = await http.get('https://api.example.com/user/123');
  return User.fromJson(response.body);
}

修饰符:.autoDispose(或使用 @Riverpod(keepAlive: true) 来禁用),以及用于参数的 .family。参见 riverpod-auto-dispose 和 riverpod-family。

创建 Provider(可修改 / Notifier)

手动方式:使用 NotifierProvider(或 AsyncNotifierProvider / StreamNotifierProvider),配合一个继承 Notifier<T>、AsyncNotifier<T> 或 StreamNotifier<T> 的 Notifier 类。重写 build();不要把逻辑放在构造函数中(此时 ref/state 尚不可用)。公共方法通过 ref.read(provider.notifier).method() 调用。

final counterProvider = NotifierProvider<CounterNotifier, int>(CounterNotifier.new);

class CounterNotifier extends Notifier<int> {
  @override
  int build() => 0;

  void increment() => state++;
}

代码生成:注解一个继承 _$ClassName 的类。重写 build();添加自定义方法。同样的规则:构造函数中不放逻辑。

@riverpod
class CounterNotifier extends _$CounterNotifier {
  @override
  int build() => 0;

  void increment() => state++;
}

使用 Provider

  • Flutter:用 ProviderScope 包裹应用。使用 Consumer、ConsumerWidget 或 ConsumerStatefulWidget 获取 ref,并调用 ref.watch(provider) 或 ref.read(provider)。
  • 仅 Dart:创建 ProviderContainer(),然后 container.read(provider) 或 container.listen(...)。完成后调用 container.dispose()。
  • 在另一个 Provider 内部:使用传给 Provider 函数的 Ref(或 Notifier 中的 this.ref)来 ref.watch / ref.read 其他 Provider。

Widget 中的示例:

return Consumer(
  builder: (context, ref, _) {
    final helloWorld = ref.watch(helloWorldProvider);
    return Text(helloWorld);
  },
);

你可以声明多个返回相同类型的 Provider;它们是相互独立的。关于 Ref、容器、修饰符和 Notifier 规则的更多细节,参见 reference.md。