[官文翻译]Flutter状态管理库Riverpod - 概念 - Provider

556 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情


Riverpod的官方文档有多国语言,但是没有汉语,所以个人简单翻译了一版。

官网文档:Riverpod

GitHub:GitHub - rrousselGit/river_pod

Pub:riverpod | Dart Package (flutter-io.cn)

译时版本:riverpod 1.0.3


Provider

现在已经安装了 Riverpod ,我们来说一下 "provider" 。

Provider 是 Riverpod 应用中最重要的部分。一个 Provider 是囊括一段状态的对象,并且可以监听这个状态。

为什么使用 provider ?

在 provider 中包装一段状态:

  • 可在多个位置简单地访问该状态。Provider 可以完整替代如Singletons、Service Locators、依赖注入或 InheritedWidget 的模式。
  • 简化该状态和其它内容的绑定。以前挣扎于将多个对象合并成一个?该场景已在 provider 中内建。
  • 可优化性能。无论是过滤组件重新构建或者是缓存耗时的状态计算;provider 确保只有状态改变影响的部分会重新计算。
  • 增加了应用的测试性。使用 provider ,不再需要复杂的 setUp/tearDown 步骤。而且,任何 provider 在测试中都可以被重写产生不同的行为,这样可以容易地测试很明确的行为。
  • 可以和其它高级特性集成,如 logging (日志)或 pull-to-refresh (拉取刷新)。

创建一个 provider

Provider 有多种版本,但是它们的运行方式是相同的。

最常见的用法是如下将它们声明为全局常量:

final myProvider = Provider((ref) {
  return MyValue();
});

注意事项

不用害怕全局层面的 provider 。 Provider 完全是不可变的。声明一个 provider 和声明一个函数没什么不同,并且 provider 是可测试和维护的。

该片段有三个组件:

  • final myProvider,变量的声明。该变量会在后面用来读取 provider 的状态。Provider 应该总是 final 的。
  • Provider,我们决定使用的 provider 。 Provider 是所有 provider 里最基础的。它暴露的对象不会改变。可以用其它 provider 如 StreamProvider 或 StateNotifierProvider 代替 Provider,可以改变值的交互方式。
  • 创建共享状态的一个函数。该函数总是接收一个叫作 ref 的对象作为参数。该对象可以让我们读取其它 provider,当 provider 的状态在破坏时进行一些操作,或者更多其它的处理。

传递给 provider 的函数返回的对象类型取决于使用的 provider。例如,Provider 的函数可以创建任何对象。另一方面,StreamProvider 的回调会期望返回一个 Stream

信息

可以无限制地定义多个 provider 。与使用 package:provider 形成对照, Riverpod 允许创建多个 provider 暴露同样类型的状态:

final cityProvider = Provider((ref) => > 'London');
final countryProvider = Provider((ref) => 'England');

事实上,两个 provider 创建了一个 String ,不会造成任何问题。

注意

为了使 provider 正常运转,必须在 Flutter 应用的根添加 ProviderScope :

void main() {
  runApp(ProviderScope(child: MyApp()));
}

不同类型的 Provider

有多种类型的 provider 用于多种不同的使用场景。

由于所有的这些 provider 都可用,有时候何时使用一种 provider 而不是另一种,会难于理解。参考下面的表格来选择最适合提供给组件树的 provider 。

Provider 类型Provider 创建函数使用场景示例
Provider返回任意类型服务类 / 计算属性(过滤列表)
StateProvider返回任意类型过滤条件 / 简单的状态对象
FutureProvider返回任意类型的 Future调用 API 的结果
StreamProvider返回任意类型的 StreamAPI的结果 stream
StateNotifierProvider返回 StateNotifier 的子类复杂的状态对象,除了接口之外不可变
ChangeNotifierProvider返回 ChangeNotifier 的子类需要可变性的复杂状态对象

警告

所有的 provider 都有它们的使用目的,因为使用可变状态的问题,ChangeNotifierProvider 不建议用于可扩展的应用。它存在于 flutter_riverpod 包中,提供了从package:provider 迁移的简单路径,并且允许一些 Flutter 特定的使用场景,如集成一些 Navigator 2 的包。

Provider Modifier(修饰符)

所有的 Provider 都内建有向不同的 provider 里添加附加功能的方式。

它们可能会为 ref 对象添加新特性 或者 轻微改变 provider 被消费的方式。 Modifier(修饰符)可用于所有的 provider ,和命名式构造函数的语法相似:

final myAutoDisposeProvider = StateProvider.autoDispose<int>((ref) => 0);
final myFamilyProvider = Provider.family<String, int>((ref, id) => '$id');

这时候,有两个修饰符可用:

  • .autoDispose,它会使 provider 在状态不再被监听时销毁状态。
  • .family,它允许用外部参数创建 povider 。

注意:

一个 provdier 可以同时使用多个 modifier :

final userProvider = FutureProvider.autoDispose.family<User, int>((ref, userId) async {
  return fetchUser(userId);
});

以上为 Provider 的指南。

可以继续阅读 如何读取 provider 。 或者,可以阅读参考 如何绑定 provider