Flutter 入门与实战(九十):使用 BlocConsumer 同时构建响应式组件和监听状态

1,989 阅读3分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动。

前言

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

BlocConsumer实现机制

BlocConsumer 像是 BlocBuilderBlocListener 的聚合组件,支持构建响应式组件的同时监听状态变化。同时也支持按条件刷新组件或响应状态变化监听回调。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 回调方法。

再来看BlocConsumerbuilder 方法:

@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 实现,而在 BlocBuilderbuilderWhen 中,会根据 listenWhen 的返回值来决定是否调用 listener 回调方法,从而实现了 BlocBuilderBlocListener 的聚合。

BlocConsumer 应用

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

代码对别

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

总结

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

我是岛上码农,微信公众号同名,这是Flutter 入门与实战的专栏文章,提供体系化的 Flutter 学习文章。对应源码请看这里:Flutter 入门与实战专栏源码。如有问题可以加本人微信交流,微信号:island-coder

👍🏻:觉得有收获请点个赞鼓励一下!

🌟:收藏文章,方便回看哦!

💬:评论交流,互相进步!