flutter_bloc:是否可在Bloc/Cubit类内部存储业务共享变量
回答
两种实现方式都能跑,但结合Cubit/Bloc的设计原则和你当前的业务场景,优先选把phoneNumber作为公共字段放到AuthState基类里,不推荐直接把phoneNumber作为私有属性存在Cubit内部。
为啥不推荐直接在Cubit里存phoneNumber
- 会造成数据源不唯一:你现在的代码里,
PhoneAuthOTPSent、PhoneAuthenticated、PhoneAuthOTPVerified这些子状态本来就已经带了phoneNumber字段,要是Cubit里再存一份,同一份数据有两个存储位置,后续改逻辑很容易出现两边值不一致的问题——比如改了Cubit里存的手机号忘了同步更新到State,UI层读State拿到的还是旧值,排查起来非常麻烦。 - UI层取值麻烦:认证流程里多个页面都需要用到手机号,比如输OTP页要展示「验证码已发送至13xxxxxxxxx」,密码重置页要回显当前手机号,要是手机号存在Cubit私有属性里,要么得额外写getter暴露,要么跨页面跳转时反复传参,远不如直接通过
BlocBuilder读State拿值方便。 - 状态恢复困难:如果App在后台被系统回收,Bloc自带的状态恢复机制可以直接还原State里存储的所有字段,存在Cubit私有属性里的值会随着实例销毁直接丢失,用户回到App就得重新输手机号,体验很差。
把phoneNumber放到AuthState基类的优势
- 彻底消除冗余代码:你现在每个业务方法(
sendOTPMessageToPhoneNumber/verifyOTPToken/sendResetPasswordOtp等)都要把phoneNumber作为参数传一遍,把字段抽到基类后,只要在第一步用户输入手机号后把值存到State里,后续所有内部方法直接读state.phoneNumber就行,不用反复在方法签名里加参数,调用的时候也不用来回传值。 - 符合单向数据流原则:整个认证流程的所有公开数据都存在State里,Cubit只负责逻辑处理、更新State,UI层只订阅State变化,整个链路的数据流向非常清晰,不会有隐式的私有变量影响逻辑。
- 改造成本极低:你现在的各个子状态本来就已经在传
phoneNumber,只要把这个字段统一抽到基类,删掉子类里重复的字段定义就行,不用大改现有逻辑。
具体改造参考
先调整AuthState基类:
abstract class AuthState { final String phoneNumber; const AuthState({this.phoneNumber = ''}); // 方便子类更新状态时复用公共字段 AuthState copyWith({String? phoneNumber}); }
之后所有子状态继承这个基类即可,第一次拿到用户输入的手机号调用checkPhoneAuthentication时,把值存入后续emit的所有状态中,后续的OTP发送、验证、密码重置等方法,就不需要再单独传phoneNumber参数了,直接从state.phoneNumber取值即可。
补个小提醒:你现在代码里的全局
phoneAuthFailedState常量记得也补上phoneNumber字段,不然出错状态下UI拿不到当前手机号;另外loginWithCredentianls方法名拼写有误,正确拼写是loginWithCredentials。
当然如果你确定这个手机号完全不需要给UI层使用、流程中不会变更、也不需要状态恢复,存在Cubit里也不会出什么大问题,但就你当前的认证流程场景来看,放在State里是维护成本最低、最不容易出bug的方案。
内容的提问来源于stack exchange,提问作者R3HP
相关产品推荐
相关产品推荐

