Flutter Bloc实现Japa计数器时如何保留原有增减计数方法
如何在Bloc架构中复用原有计数器业务方法
问题背景
- 正在开发的Japa计数器支持计数增减、圈数自动累计:念珠计数达到108时圈数自动+1,念珠计数重置为0循环计数
- 早期使用
setState做状态管理时,交互逻辑非常直观:点击「+」按钮调用Counter类的incrementCounter方法,点击「-」按钮调用decrementCounter方法即可完成所有计数逻辑 - 为学习Bloc重构应用后,受事件-状态模型限制,之前的实现只能通过构造函数传入计算好的新值更新状态,无法直接调用封装好的原有业务方法,和最初的业务设计存在偏差,更希望保留调用业务方法的实现逻辑
具体实现方案
完全可以在Bloc层复用原有Counter类的所有业务方法,不需要把计数规则拆到Bloc层重新实现,核心思路是把Counter类实例直接作为Bloc的状态载体,事件触发时先调用实例自身的业务方法更新值,再将更新后的实例作为新状态发出,具体实现步骤:
- 保留原有
Counter类的全部业务逻辑,不需要修改incrementCounter、decrementCounter的内部实现,仅补充状态拷贝需要的copyWith方法即可:
class Counter { int malaCount; // 念珠计数 int lapCount; // 圈数 Counter({this.malaCount = 0, this.lapCount = 0}); // 原有递增逻辑完全保留 void incrementCounter() { malaCount++; if (malaCount >= 108) { lapCount++; malaCount = 0; } } // 原有递减逻辑完全保留 void decrementCounter() { if (malaCount == 0) { if (lapCount > 0) { lapCount--; malaCount = 107; } return; } malaCount--; } // 补充copyWith保证状态不可变 Counter copyWith({int? malaCount, int? lapCount}) { return Counter( malaCount: malaCount ?? this.malaCount, lapCount: lapCount ?? this.lapCount, ); } }
- 定义极简的Bloc事件,不需要携带任何计数参数,只需要标记操作类型:
abstract class CounterEvent {} class CounterIncrementPressed extends CounterEvent {} class CounterDecrementPressed extends CounterEvent {}
- 在Bloc的事件处理器中直接调用原有业务方法,不需要手动计算新的计数值:
class CounterBloc extends Bloc<CounterEvent, Counter> { CounterBloc() : super(Counter()) { on<CounterIncrementPressed>((event, emit) { // 先拷贝当前状态 final newState = state.copyWith(); // 直接调用原有递增方法,所有计数逻辑走原有封装 newState.incrementCounter(); // 发出新状态 emit(newState); }); on<CounterDecrementPressed>((event, emit) { final newState = state.copyWith(); newState.decrementCounter(); emit(newState); }); } }
如果习惯用不可变类,也可以把
Counter的属性改成final修饰,让incrementCounter、decrementCounter直接返回新的Counter实例,连copyWith都可以省略,更符合Bloc的状态不可变要求。
方案优势
- 100%复用原有业务代码,不需要重写计数、圈数累计规则,和最初的设计逻辑完全一致
- 业务逻辑仍然收敛在
Counter类内部,后续调整计数规则(比如修改满值阈值、增加特殊计数逻辑)只需要改Counter类的对应方法,不需要动Bloc层代码 - 完全符合Bloc的事件驱动规范,UI层只需要发送对应事件,不需要感知内部计数实现,分层边界清晰
内容的提问来源于stack exchange,提问作者gopi krishna
相关产品推荐
相关产品推荐

