BlocBuilder与BlocListener状态变更调用规则差异咨询
核心差异本质
你理解偏差的核心点是:BlocBuilder的builder首先是Flutter标准组件的构建函数,从来不是仅响应bloc state变更触发;而BlocListener的listener是完全绑定在bloc state流上的副作用回调,和Flutter组件构建生命周期无关。
BlocBuilder会出现非state变更触发调用的常见场景
这些就是文档里提到的“额外调用”,和bloc本身的state变化完全无关:
- 组件首次挂载到组件树时,会执行第一次初始构建,这个时候没有任何state变更发生
- 父组件触发重建时(比如父组件调用
setState、上层路由状态更新、全局依赖的Theme/MediaQuery数据变化),子树里的BlocBuilder会作为子组件被连带强制重建,builder会重新执行,哪怕监听的bloc没有发出任何新state - 组件因为Key变化、条件渲染切换等原因被销毁后重新插入组件树时,会重新执行
builder完成初始化,此时state也没有发生变化 - 举个可复现的极简例子:在BlocBuilder外层放一个每秒调用一次
setState刷新无关文本的组件,哪怕bloc全程没有add任何事件、没有推送任何新state,你也会观察到builder每秒执行一次。
BlocListener的调用保证为什么不一样
listener是流订阅的副作用回调,它的触发逻辑完全和组件构建解耦:
- 不会在组件初始挂载、组件重建、组件重挂载等场景被触发
- 仅当bloc的state流真正推送了一个与前值不相等的新state时,才会精准执行一次,不会因为Flutter框架层面的行为出现多余调用
- 也不会出现“因为组件重建没赶上state变更漏掉回调”的情况,只要流订阅还生效,state变更就一定会触发一次listener
内容的提问来源于stack exchange,提问作者Savvy
相关产品推荐
相关产品推荐

