在Bloc中使用Freezed库时应选择密封类还是构造函数实现方式?
Flutter Bloc 结合 Freezed 两种实现方案的场景对比与选型
方案1:密封类(联合类型)实现
这是Freezed最原生的密封类用法,把不同的状态拆成独立的子类,同一时间只会存在其中一个子类实例:
abstract class HomeState with _$HomeState { const factory HomeState.initial() = _Initial; const factory HomeState.addNewNoteButtonClicked(@Default(false) bool isClicked) = AddNewNoteClicked; factory HomeState.addNewNote( Note value) = AddNewNote; }
适用场景
- 页面状态互斥:同一时间只会展示一种状态,比如加载中、加载成功、加载失败,三种状态不可能同时出现
- 不同状态携带的参数差异大:比如
initial状态不需要任何参数,addNewNote只需要传Note对象,不会产生冗余的无效字段,也避免了可空字段带来的空安全隐患 - 状态分支处理逻辑复杂:需要在
BlocBuilder/BlocListener中针对不同状态做完全独立的UI渲染或逻辑处理,Freezed自动生成的when/map方法可以强制要求覆盖所有状态分支,不会出现漏处理的情况
方案2:统一构造函数实现
本质是只声明一个状态类,所有状态变化都通过修改类的属性实现:
abstract class HomeState with _$HomeState { const factory HomeState({ required Note value, required bool isClicked, }) = AddNewNoteClicked; factory HomeState.init() => HomeState( value: Note(value: ''), isClicked: false, ); }
适用场景
- 状态属性可共存:多个状态属性不是互斥关系,可以同时生效,比如笔记编辑页同时需要存当前编辑的内容、按钮是否可点击、是否正在上传等多个并行的属性
- 属性复用度高:所有属性都是页面全局需要用到的,不会出现某个状态下大量字段无意义的情况
- 逻辑简单不需要多分支判断:UI不需要根据状态类型做完全不同的渲染,只是根据属性值调整局部UI,不需要写多分支判断逻辑,代码更简洁
选型判断规则
- 优先判断状态是否互斥:如果状态之间是互斥关系,直接选密封类实现;如果多个属性可以同时生效,选统一构造实现
- 看参数重合度:如果不同状态需要的参数重合度低于30%,选密封类避免冗余字段;如果所有属性都是全局通用,选统一构造
- 看逻辑复杂度:如果需要针对不同状态做独立的跳转、弹窗、页面切换等逻辑,选密封类避免漏处理分支;如果只是局部UI调整,选统一构造更省事
内容的提问来源于stack exchange,提问作者Mariam Albarghouti
相关产品推荐
相关产品推荐

