12 Consumer
Consumer是 Provider 中比较有意思的东西,它本身是一个 StatelessWidget , 只是在 build中通过 Provider.of(context) 帮你获取到 InheritedWidget 共享的 value 。
final Widget Function(BuildContext context, T value, Widget child) builder;
@override
Widget build(BuildContext context) {
return builder(
context,
Provider.of<T>(context),
child,
);
}那我们直接使用 Provider.of(context) ,不使用 Consumer可以吗?
当然可以,但是你还记得前面,我们在介绍 InheritedWidget 时所说的:
传入的
context代表着这个Widget的Element在InheritedElement里被“登记”到_dependents了。
Consumer做为一个单独 StatelessWidget ,它的好处就是 Provider.of(context) 传入的 context 就是 Consumer它自己。 这样的话,我们在需要使用 Provider.value 的地方用 Consumer 做嵌套, InheritedWidget 更新的时候,就不会更新到整个页面 , 而是仅更新到 Consumer这个 StatelessWidget 。
所以 Consumer贴心的封装了 context 在 InheritedWidget 中的“登记逻辑”,从而控制了状态改变时,需要更新的精细度。
同时库内还提供了 Consumer2 ~ Consumer6 的组合,感受下 :
@override
Widget build(BuildContext context) {
return builder(
context,
Provider.of<A>(context),
Provider.of<B>(context),
Provider.of<C>(context),
Provider.of<D>(context),
Provider.of<E>(context),
Provider.of<F>(context),
child,
);这样的设定,相信用过 BLoC 模式的同学会感觉很贴心,以前正常用做 BLoC 时,每个 StreamBuilder 的 snapShot 只支持一种类型,多个时要不就是多个状态合并到一个实体,要不就需要多个StreamBuilder嵌套。
当然,如果你想直接利用 LayoutBuilder 搭配 Provider.of(context) 也是可以的:
LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
var counter = Provider.of<ProviderModel>(context);
return new Text("Provider ${counter.count.toString()}");
}其他的还有 ValueListenableProvider 、FutureProvider、StreamProvider等多种 Provider ,可见整个 Provider 的设计上更贴近 Flutter 的原生特性,同时设计也更好理解,并且兼顾了性能等问题。
Provider 的使用指南上,更详细的 Vadaski 的 《Flutter | 状态管理指南篇——Provider》 已经写过,我就不重复写轮子了,感兴趣的可以过去看看。
学员评价