Freezed+Bloc:如何在Bloc Listener中判断状态并获取特定状态变量
如何在Bloc监听器中访问Success状态的code变量
我正在学习如何在Bloc监听器中根据状态,以及仅在Success状态中存在的code变量执行代码。需要在Listener中判断当前是否处于Success状态,并获取该状态下的code值。
现有代码实现
状态定义
@freezed class ExampleState with _$ExampleState { const factory ExampleState.initial() = _Initial; const factory ExampleState.success(int code) = _Success; const factory ExampleState.error() = _Error; }
Bloc逻辑
class ExampleBloc extends Bloc<ExampleEvent, ExampleState> { ExampleBloc() : super(_Initial()) { on<_ChangeCode>((event, emit) { if(state is _Success){ int stateCode = (state as _Success).code; debugPrint("Ey, I got the current code: $stateCode"); // 希望在Listener中以类似方式访问该code变量 } emit(ExampleState.success(event.newCode)); }); } }
待完善的Listener代码
listener: (context, state) { // 希望判断当前状态是否为success // 希望在state.code == 5时打印内容 },
我尝试的两种方案
方案一:为所有状态添加code变量
修改状态定义,给每个状态都添加code参数,这样可以直接通过state.code访问:
@freezed class ExampleState with _$ExampleState { const factory ExampleState.initial(int code) = _Initial; const factory ExampleState.success(int code) = _Success; const factory ExampleState.error(int code) = _Error; }
对应的Listener代码:
listener: (context, state) { debugPrint(state.code.toString()); },
但这个方案的缺点很明显:很多状态(比如initial、error)根本不需要code字段,长期维护会产生冗余代码,还可能引入无意义的默认值。
方案二:将Success状态类设为公开
把_Success前的下划线去掉,改为公开的Success类:
@freezed class ExampleState with _$ExampleState { const factory ExampleState.initial() = _Initial; const factory ExampleState.success(int code) = Success; const factory ExampleState.error() = _Error; }
对应的Listener代码:
listener: (context, state) { if(state is Success){ debugPrint(state.code.toString()); if (state.code == 5) { debugPrint('Code matches 5!'); } } },
但我不确定这种做法是否属于不良实践,因为默认生成的状态类是私有的,不知道是否应该修改这个规则。
解答:公开特定状态类是合理实践
Freezed默认生成私有状态类(带下划线)是为了强制开发者通过工厂构造函数创建状态,避免直接实例化状态子类。但将需要外部访问的状态类设为公开是完全合规且推荐的做法,原因如下:
- 当UI层或其他外部代码需要区分状态类型并访问特定状态的属性时,公开对应的状态类是最直接、类型安全的方式。
- 避免了方案一中冗余字段的问题,保持状态结构的清晰性。
另外,推荐使用Freezed提供的when方法进行模式匹配,代码会更简洁且符合Freezed的设计理念:
listener: (context, state) { state.when( initial: () {}, // 处理初始状态 success: (code) { if (code == 5) { debugPrint('Code is 5!'); } }, error: () {}, // 处理错误状态 ); }
这种方式不需要手动进行类型判断和转换,编译器会自动检查所有状态分支,避免遗漏情况。
内容的提问来源于stack exchange,提问作者BrML
相关产品推荐
相关产品推荐

