同一Bloc/Cubit下如何让多个BlocBuilder分别响应不同事件
解决方案
完全可以用单个CounterCubit实现需求,无需拆分创建两个独立的Cubit类。
问题原因
你当前遇到的双向触发问题,是因为默认BlocBuilder会监听对应Cubit的所有状态变化,而你现在直接用int作为Cubit的状态类型,无论是increment还是decrement操作都会修改这个int值,自然会触发所有绑定了该Cubit的BlocBuilder重建。
实现步骤
1. 自定义带操作标识的状态类
替换原来直接用int作为状态的设计,新增枚举标识最后一次触发的操作类型:
// 定义计数器操作类型枚举 enum CounterOperation { increment, decrement, initial } // 自定义计数器状态类 class CounterState { final int count; final CounterOperation lastOp; CounterState({required this.count, required this.lastOp}); }
2. 修改CounterCubit逻辑
调整Cubit的状态类型,每次emit状态时携带当前操作标识:
class CounterCubit extends Cubit<CounterState> { // 初始状态计数为0,操作类型为初始值 CounterCubit() : super(CounterState(count: 0, lastOp: CounterOperation.initial)); void increment() { emit(CounterState(count: state.count + 1, lastOp: CounterOperation.increment)); } void decrement() { emit(CounterState(count: state.count - 1, lastOp: CounterOperation.decrement)); } }
3. 用buildWhen过滤BlocBuilder的触发时机
BlocBuilder提供的buildWhen参数可以自定义是否需要触发重建,根据状态携带的操作类型过滤即可:
Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ // 仅increment操作触发重建 BlocBuilder<CounterCubit, CounterState>( buildWhen: (previous, current) => current.lastOp == CounterOperation.increment, builder: (context, state) { return Text('Increment ${state.count}', style: textTheme.headline2); }, ), // 仅decrement操作触发重建 BlocBuilder<CounterCubit, CounterState>( buildWhen: (previous, current) => current.lastOp == CounterOperation.decrement, builder: (context, state) { return Text('Decrement ${state.count}', style: textTheme.headline2); }, ), ] )
方案说明
这种方式既保留了单个Cubit统一管理计数器状态的合理架构,也避免了多Cubit带来的状态同步成本,是官方推荐的状态拆分过滤实现方案。
内容的提问来源于stack exchange,提问作者Devendra
相关产品推荐
相关产品推荐

