Flutter 开发实战

235课时
2.1K学过
8分

课程评价 (0)

请对课程作出评价:
0/300

学员评价

暂无精选评价
2分钟

12 Consumer

ConsumerProvider 中比较有意思的东西,它本身是一个 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 代表着这个 WidgetElementInheritedElement 里被“登记”到 _dependents 了。

Consumer做为一个单独 StatelessWidget它的好处就是 Provider.of(context) 传入的 context 就是 Consumer它自己。 这样的话,我们在需要使用 Provider.value 的地方用 Consumer 做嵌套, InheritedWidget 更新的时候,就不会更新到整个页面 , 而是仅更新到 Consumer这个 StatelessWidget

所以 Consumer贴心的封装了 contextInheritedWidget 中的“登记逻辑”,从而控制了状态改变时,需要更新的精细度。

同时库内还提供了 Consumer2Consumer6 的组合,感受下 :

  @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 时,每个 StreamBuildersnapShot 只支持一种类型,多个时要不就是多个状态合并到一个实体,要不就需要多个StreamBuilder嵌套。

当然,如果你想直接利用 LayoutBuilder 搭配 Provider.of(context) 也是可以的:

LayoutBuilder(
            builder: (BuildContext context, BoxConstraints constraints) {
              var counter =  Provider.of<ProviderModel>(context);
              return new Text("Provider ${counter.count.toString()}");
            }

其他的还有 ValueListenableProviderFutureProviderStreamProvider等多种 Provider ,可见整个 Provider 的设计上更贴近 Flutter 的原生特性,同时设计也更好理解,并且兼顾了性能等问题。

Provider 的使用指南上,更详细的 Vadaski《Flutter | 状态管理指南篇——Provider》 已经写过,我就不重复写轮子了,感兴趣的可以过去看看。