Flutter中Bloc(RxDart)修改变量值后为空的问题求助
问题:Flutter RxDart Bloc中oldPin变量赋值后始终为空
在Flutter中使用基于RxDart的Bloc模式开发时,尝试通过UI调用checkValidateConfirmNewPin方法修改ChangePinBloc类中的oldPin变量,并在changePin方法中使用该变量,但oldPin始终为空字符串。
相关代码
Bloc类代码
class ChangePinBloc { final ChangePinRepository _changePinRepository = ChangePinRepository(); final _isValidateConfirmNewPinController = PublishSubject(); String oldPin = ''; Stream get isValidateConfirmNewPinStream => _isValidateConfirmNewPinController.stream; void checkValidateConfirmNewPin( {required String newPinCode, required String oldPinCode}) { if (newPinCode == oldPinCode) { oldPin = oldPinCode; changePin(newCode: newPinCode); isValidateConfirmPin = true; _isValidateConfirmNewPinController.sink.add(isValidateConfirmPin); } else { isValidateConfirmPin = false; _isValidateConfirmNewPinController.sink.add(isValidateConfirmPin); } } void changePin({required String newCode}) async { changePinRequestBody['deviceId'] = oldPin; } dispose() { } }
完整UI代码
void main() { final changePinBloc = ChangePinBloc(); @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: StreamBuilder( stream: changePinBloc.isValidateConfirmNewPinStream, builder: (context, AsyncSnapshot pinValidateSnapshot) { return Stack( children: [ Positioned.fill( child: Column( children: [ const PinChangeSettingTitle( title: CONFIRM_NEW_PIN_TITLE, subTitle: CONFIRM_NEW_PIN_SUBTITLE, ), const SizedBox( height: margin50, ), Padding( padding: const EdgeInsets.only( left: margin50, right: margin50), child: PinCodeField( pinLength: 6, onComplete: (value) { changePinBloc.checkValidateConfirmNewPin( newPinCode: value, oldPinCode: widget.newCodePinValue!, ); }, onChange: () {}, ), ) ], ), ), pinValidateSnapshot.hasData ? pinValidateDataState(pinValidateSnapshot, changePinBloc) : const Positioned.fill( child: SizedBox(), ), ], ); }, ), ), ); } }
问题原因
- Bloc实例生命周期管理错误:你的UI代码存在语法错误,错误地在
main()函数(实际属于Widget代码块)中定义changePinBloc。这种写法会导致Widget重建时可能创建新的Bloc实例,之前赋值的oldPin会随着旧实例被销毁而丢失,新实例的oldPin始终是初始空字符串。 - 条件分支未触发:如果
newPinCode == oldPinCode的条件不成立,oldPin根本不会被赋值,后续调用changePin时自然为空。
解决方案
1. 正确管理Bloc实例生命周期
将Bloc实例放在StatefulWidget的State类中初始化,确保整个Widget生命周期内使用同一个实例:
class PinConfirmPage extends StatefulWidget { final String? newCodePinValue; // 其他参数 const PinConfirmPage({Key? key, this.newCodePinValue}) : super(key: key); @override State<PinConfirmPage> createState() => _PinConfirmPageState(); } class _PinConfirmPageState extends State<PinConfirmPage> { late final ChangePinBloc changePinBloc; @override void initState() { super.initState(); // 仅在初始化时创建一次Bloc实例 changePinBloc = ChangePinBloc(); } @override void dispose() { // 页面销毁时释放Bloc资源 changePinBloc.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: StreamBuilder( stream: changePinBloc.isValidateConfirmNewPinStream, builder: (context, AsyncSnapshot pinValidateSnapshot) { // 后续UI代码保持不变,使用同一个changePinBloc实例 return Stack(...); }, ), ), ); } }
2. 验证条件分支是否触发
在checkValidateConfirmNewPin方法中添加日志,确认条件是否满足:
void checkValidateConfirmNewPin({required String newPinCode, required String oldPinCode}) { print("输入的newPinCode: $newPinCode, 传入的oldPinCode: $oldPinCode"); print("两者是否相等: ${newPinCode == oldPinCode}"); if (newPinCode == oldPinCode) { oldPin = oldPinCode; print("赋值后的oldPin: $oldPin"); changePin(newCode: newPinCode); isValidateConfirmPin = true; _isValidateConfirmNewPinController.sink.add(isValidateConfirmPin); } else { isValidateConfirmPin = false; _isValidateConfirmNewPinController.sink.add(isValidateConfirmPin); } }
同时在changePin方法中添加日志,确认调用时的oldPin值:
void changePin({required String newCode}) async { print("changePin方法中oldPin的值: $oldPin"); changePinRequestBody['deviceId'] = oldPin; }
内容的提问来源于stack exchange,提问作者La Pyae
相关产品推荐
相关产品推荐

