当前位置:网站首页>使用 BlocConsumer 同时构建响应式组件和监听状态

使用 BlocConsumer 同时构建响应式组件和监听状态

2022-07-04 21:33:00 InfoQ

前言

上一篇我们利用了 
BlocListener
 监听状态变化并做一些相应的处理,同时使用了 
BlocBuilder
 构建了响应式界面。回顾代码,我们会发现存在冗余的部分,我们需要将 
BlocBuilder
 作为 
BlocListener
 的子组件,这其实有点别扭,因为 
BlocBuilder
构建的页面按说不应该是 
BlocListener
 的子组件,而是同级结构。那有没有更好的方式解决这个问题呢,事实上,flutter_bloc 给出了 
BlocConsumer
 来解决这一问题。

BlocConsumer实现机制

BlocConsumer
 像是 
BlocBuilder
和 
BlocListener
 的聚合组件,支持构建响应式组件的同时监听状态变化。同时也支持按条件刷新组件或响应状态变化监听回调。BlocConsumer 的构造方法如下:

const BlocConsumer({
 Key? key,
 required this.builder,
 required this.listener,
 this.bloc,
 this.buildWhen,
 this.listenWhen,
}) : super(key: key);

其中参数说明如下:

  • builder
    :响应式组件构造方法,和 
    BlocBuilder
     的相同。
  • listener
    :状态变化处理监听回调函数,和 
    BlocListener
     的定义一致。
  • bloc
    :可选的 
    Bloc
     状态对象,如果没有指定,会自动从当前的
    BuildContext
     中查找对应类型的状态对象。
  • buildWhen
    :可选参数,接收前后的状态对象,可以根据前后状态对象返回 
    bool
     值,若为 
    true
     才会刷新组件。
  • listenWhen
    :可选参数,接收前后的状态对象,可以根据前后状态对象返回 
    bool
     值,若为 
    true
     才会调用 
    listener
     回调方法。

再来看
BlocConsumer
的 
builder
 方法:

@override
Widget build(BuildContext context) {
 if (widget.bloc == null) context.select<B, int>(identityHashCode);
 return BlocBuilder<B, S>(
 bloc: _bloc,
 builder: widget.builder,
 buildWhen: (previous, current) {
 if (widget.listenWhen?.call(previous, current) ?? true) {
 widget.listener(context, current);
 }
 return widget.buildWhen?.call(previous, current) ?? true;
 },
 );
}

可以看到,实际实现还是基于 
BlocBuilder
 实现,而在 
BlocBuilder
 的 
builderWhen
 中,会根据 
listenWhen
 的返回值来决定是否调用 
listener
 回调方法,从而实现了 
BlocBuilder
BlocListener
 的聚合。

BlocConsumer 应用

我们对上一篇的代码进行改造,然后看一下两部分代码的比对,如下图所示。

null
可以看到,代码的行数其实没什么改变,但是整个代码的层级会更清晰,这样会使得代码更易于维护,完整代码已经上传至:
BLoC 状态管理代码

总结

本篇介绍了 
BlocConsumer
 的实现机制,以及比对了 
BlocBuilder
 和
BlocListener
分开实现时的差异。通过对比发现可以看到,
BlocConsumer
 这种聚合了 
BlocBuilder
 和 
BlocListener
 的方式在这种场景下的代码层级更清晰,也易于维护。
null
原网站

版权声明
本文为[InfoQ]所创,转载请带上原文链接,感谢
https://xie.infoq.cn/article/cf58f5efef5f99d1629810548