pub:riverpod | Dart Package (flutter-io.cn)
译时版本: 2.4.5
之前翻译过 RiverPod 的官方文档,现在随着版本更新,官方文档又多了很多新内容,所以再补充翻译一下。
之前翻译过的内容,现在官方文档有中文了。
Flutter状态管理库Riverpod官方文档翻译汇总 - 掘金 (juejin.cn)
快速开始
该部分是为了习惯使用 Provider 想要了解 Riverpod 的目标人群而设计。
在开始之前先读一下 getting started 并尝试一个 sandbox 小例子来测试下 RiverPod 的特性吧。
如果你尝试之后很喜欢,那你绝对应该考虑一下迁移到 RiverPod。
实际上,从 Provider 迁移到 RiverPod 相当简单。
迁移只需要几个步骤,它会以 增量 的方式完成。
先从 ChangeNotifierProvider
开始
转换为 RiverPod ,如果不使用最新独特的 ASAP 特性, 继续使用 ChangeNotifier
也没什么问题。
实际上,以下代码是个很好的开始:
dart
// 如果现有的代码是
class MyNotifier extends ChangeNotifier {
int state = 0;
void increment() {
state++;
notifyListeners();
}
}
// ... 只需要添加以下内容!
final myNotifierProvider = ChangeNotifierProvider<MyNotifier>((ref) {
return MyNotifier();
});
正如所见,Riverpod 暴露了一个 ChangeNotifierProvider 类,它恰好支持从 pkg:Provider 迁移过来。
要记住,不推荐在编写新代码时使用该 provider ,它不是使用 RiverPod 的最好的方式, 但是对于开始迁移,是一个优雅和非常简单的方式。
提示:
也不需要急于 马上 将 ChangeNotifier
变为更先进的 Riverpod provider。 因为需要一些范式转换,所以一上来就这么做会比较困难。
慢慢来,首先适应 RiverPod 非常重要; 然后很快就会在 pkg:riverpod 中发现 pkg:provider 中几乎绝大多数的 Provider 都有相应的完美替代。
从 树叶 开始
先从不依赖其它项的 Provider 开始,也就是说,从依赖树的树叶开始。
只要迁移了所有的树叶,之后就可以再迁移依赖树叶的 Provider 了。
换名话说,一上来先不迁移 ProxyProvider
;一旦所有依赖项都迁移完毕,再解决它们。
这样会加速和简化迁移过程,也能最少化和追踪任意错误。
Riverpod 和 Provider 可以并存
要认识到同时使用 Riverpod 和 Provider 是完全可能的。
实际上,使用 import 别名,就能同时使用两种 API 。 这样也有助于提高可读性,并移除一些有歧义的 API 。
如果打算这么做,可以考虑为代码库中引入的每一个 Provider 指定 import 别名。
信息:
高效实现 import 别名的完整指南很快就会来了。
不是必须 正确使用 Consumer
无需立即 使用 Riverpod 的 Consumer
API,意识到这一点是很重要的。
如果是刚开始迁移,正如上面提到的,或许应该先从 ChangeNotifierProvider
开始。
看一下上面定义的 myNotifierProvider
。
Since your inner code is probably depending on pkg:Provider's APIs, use the following to start consuming ChangeNotifier
s with pkg:Riverpod.
由于内部代码可能会依赖 pkg:Provider 的 API ,下面的代码可以用 pkg:Riverpod 开始消费 ChangeNotifier
。
dart
MultiProvider(
providers: [
ChangeNotifierProvider.value(value: ref.watch(myNotifierProvider.notifier)),
]
)
这种方式,只有根组件需要在一开始转换成 ConsumerWidget
。 这样做会使迁移到 pkg:Riverpod 更容易。
一次迁移一个 Provider
如果是现有的 APP ,不要尝试一下子迁移所有的 Provider !
While you should strive toward moving all your application to Riverpod in the long-run, don't burn yourself out .
一次只迁移一个 Provider。
对于上面的例子,完整 地将 myNotifierProvider
迁移到 Riverpod 意味着要写以下代码:
dart
class MyNotifier extends Notifier<int> {
@override
int build() => 0;
void increment() => state++;
}
final myNotifierProvider = NotifierProvider<MyNotifier, int>(MyNotifier.new);
。。然后也 需要改变 provider 的消费方式,也就是说,对于该 provider 的每个 context.watch
,都需要改写成 ref.watch
。
该操作会花些时间,也可能会导致一些错误,所以不必急于一次性全部改完。
迁移 ProxyProvider
在 pkg:Provider 中,ProxyProvider
用来绑定其它 provider 提供的值; 它的构建依赖依赖其它 provider 的值,是响应式的。
使用 RiverPod ,得到的是,Provider 默认是可组合的;因此,迁移 ProxyProvider
时,如果是想声明对另一个 provider 的直接依赖,只需改为 ref.watch
(另一个 provider)。
如果有值的话, 能感觉到用 RiverPod 绑定值更简单直接; 用此方式,迁移会大大简化代码。
此外,也没有将两个或以上 provider 绑定在一起的处理,只需要添加另外一个 ref.watch
就能更深进行了。
饿汉式
由于 Riverpod 的 provider 是 final 的全局变量,所以它们默认是懒加载(懒汉式)的。
如果想要初始化一些热身数据或者在启动时初始化一个有用的服务,最好的方式是在使用 MultiProvider
的地方读取 provider 。
If you need to initialize some warm-up data or a useful service on startup, the best way to do it is to first read your provider in the place where you used to put MultiProvider
.
换句话说,由于 RiverPod 不能被强制初始化为饿汉式,在启动阶段可以读取并缓存它们,这样在应用空闲时他们随时都存在并可被读取。
[这里是]关于 pkg:Riverpod provider 饿汉式的完整指南。
代码生成
从长远 来看,建议使用代码生成。
作为附注,很有可能元编程成为一种编程方式,Riverpod 默认是使用代码生成。
不幸的是,@riverpod
还不能为 ChangeNotifierProvider
生成代码。
要克服这一占,可以使用下面的扩展方法:
dart
extension ChangeNotifierWithCodeGenExtension on Ref {
T listenAndDisposeChangeNotifier<T extends ChangeNotifier>(T notifier) {
notifier.addListener(notifyListeners);
onDispose(() => notifier.removeListener(notifyListeners));
onDispose(notifier.dispose);
return notifier;
}
}
然后,使用下面的代码生成语法暴露 ChangeNotifier
:
dart
// 忽略(用于文件): 不支持的 provider 值
@riverpod
MyNotifier example(ExampleRef ref) {
return ref.listenAndDisposeChangeNotifier(MyNotifier());
}
一旦基础 迁移完成,就可以把 ChangeNotifier
改为 Notifier
, 这样就无需临时扩展了
还是用前面的例子,"完整迁移后" 的 Notifier
会是下面这个样子:
dart
@riverpod
class MyNotifier extends _$MyNotifier {
@override
int build() => 0;
void increment() => state++;
}
只要该步骤做完,就可以认为代码库中已经没有 ChangeNotifierProvider
了,也就可以完全处理掉临时扩展了。
要记住,使用代码生成是推荐方式,不是强制的。 渐进式的迁移是不错的方式:
一次转换成代码生成语法感觉很多时 ,如果想要实现迁移,完全没有问题。
跟随该指南,后面就能再进一步迁移到代码生成。