原文链接:Optimizing performance | Riverpod
pub:riverpod | Dart Package (flutter-io.cn)
译时版本: 2.4.9
之前翻译过 Riverpod 的官方文档,现在随着版本更新,官方文档又多了很多新内容,所以再补充翻译一下。
之前翻译过的内容,现在官方文档有中文了。
Flutter状态管理库Riverpod官方文档翻译汇总 - 掘金 (juejin.cn)
改善性能
用至今为止前面看到的所有内容,已经可以构建一个完整的功能性应用了。 尽管如此,可能还是会有一些性能考量方面的问题。
本篇文章会提供一些提示和技巧来尽可能地改善代码。
警告
在进行改善之前,先确认下应用的性能指标。
改善性能产生的复杂性可能得不偿失。
使用 "select" 过滤组件/provider 的重建
你可能已经注意到了,使用 ref.watch
默认会在对象的任意属性改变时导致 consumer/provider 重新构建。
例如,监听一个 User
(用户)但是只使用它的"name"(名字)也会在"age"(年龄)改变时导致 consumer(消费者)重新构建。
但是假设有一个使用属性子集的 consumer(消费者),想在其它属性改变时避免重新构建组件。
可使用 provider 的 select
功能来实现。
这样做时,ref.watch
不再返回整个对象,而是返回被选择的属性。
这样 consumers/provider 现在只会在这些被选择的属性改变时进行重新构建。
class User {
late String firstName, lastName;
}
@riverpod
User example(ExampleRef ref) => User()
..firstName = 'John'
..lastName = 'Doe';
class ConsumerExample extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// 代替以下代码:
// String name = ref.watch(provider).firstName!;
// 可以写为:
String name = ref.watch(exampleProvider.select((it) => it.firstName));
// 这会使组件只监听 "firstName" 的改变。
return Text('Hello $name');
}
}
信息
select
想调用多少次就调用多少次。只要你想,每个属性调用各调用一次都可以。
警告
被选择的属性预期是不可变的。 返回
List
并修改它们不会触发重新构建。
警告
使用
select
会略微降低单个读操作的速度,并且会增加一些代码的复杂度。
如果 “其它属性” 很少发生改变,那可能不值得这么做。
选择异步属性
假设在尝试优化一个正在监听其它 provider 的 provider ,那其它 provider 很可能是异步的。
正常情况下,会使用 ref.watch(anotherProvider.future)
来获取值。
问题是,select
只会用于 AsyncValue
– 这个是不能 await (等待)的。
为了该达到该目的,可以使用 selectAsync
代替。对于异步代码这是唯一的,然后要使 provider 产出的数据能进行 select
操作。
它的用法和 select
类似,不同的是会返回 Future
:
@riverpod
Object? example(ExampleRef ref) async {
// 等待 user 可用,然后只监听 "firstName" 属性
final firstName = await ref.watch(
userProvider.selectAsync((it) => it.firstName),
);
// TODO 使用 "firstName" 来获取其它信息
}