You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BlocBuilder的buildWhen与BlocSelector的核心差异及实际表现解析

BlocBuilder的buildWhen与BlocSelector的selector实际差异解析

核心差异拆解

1. 触发时机与执行频率

  • buildWhen:仅在Bloc状态发生变更时执行。只有当Bloc发出新的状态对象时,才会调用buildWhen对比前后完整状态,返回true才触发builder重建;如果Bloc状态没变化,哪怕父组件重建,buildWhen也不会执行,builder也不会触发。
  • selector:在两个场景下都会执行:一是Bloc状态变更时,二是Widget自身触发build(比如父组件重建、自身依赖更新)时。每次执行都会从当前状态中提取目标值,只有当提取值与上一次结果不相等(默认用==判断)时,才会触发builder重建。

2. 对比逻辑的维度

  • buildWhen:对比的是完整的Bloc前后状态对象,你可以自定义任意复杂的判断逻辑。比如同时判断状态的多个字段变化、状态类型切换等。
  • selector:对比的是你指定提取的子状态/值,逻辑聚焦在你关心的部分,不需要手动处理全量状态的对比。比如只提取状态中的用户名称、某个数值,只要这个值不变,就不会触发重建。

3. 性能优化的侧重点

  • buildWhen:主要用来过滤Bloc端的无效状态更新。比如Bloc会频繁发送状态,但大部分状态变化和当前组件无关,用buildWhen直接跳过这些更新,避免进入builder逻辑。
  • selector:主要用来屏蔽Widget端的无效重建触发。即使Widget因为父组件重建等原因触发build流程,只要selector提取的值没变化,就不会重复执行builder,减少不必要的渲染操作。

4. 适用场景区分

  • 当你需要基于完整状态的复杂条件决定是否重建时,选buildWhen。比如:只有当状态从Loading切换到Success,或者Error状态的错误码发生变化时才重建。
  • 当你只关心状态中的某一个/几个特定字段,且希望在任何触发build的场景下都只在这些字段变化时才重建,选selector。比如:组件仅展示用户昵称,就用selector提取昵称字段,不管其他状态字段怎么变,只要昵称不变就不重建。

示例对比

假设Bloc状态为UserState(name: String, age: int):

使用buildWhen:

BlocBuilder<UserBloc, UserState>(
  buildWhen: (previous, current) => previous.name != current.name,
  builder: (context, state) => Text(state.name),
)

只有Bloc状态变化且name字段不同时,才会触发builder;父组件重建时,若Bloc状态未变,builder不会执行。

使用selector:

BlocSelector<UserBloc, UserState, String>(
  selector: (state) => state.name,
  builder: (context, name) => Text(name),
)

无论是Bloc状态变化导致name改变,还是父组件重建,selector都会执行;但只要name未变,builder就不会触发。

内容的提问来源于stack exchange,提问作者TpoM6oH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 18:16:38