You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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(),
                      ),
              ],
            );
          },
        ),
      ),
    );
  }
  
}

问题原因

  1. Bloc实例生命周期管理错误:你的UI代码存在语法错误,错误地在main()函数(实际属于Widget代码块)中定义changePinBloc。这种写法会导致Widget重建时可能创建新的Bloc实例,之前赋值的oldPin会随着旧实例被销毁而丢失,新实例的oldPin始终是初始空字符串。
  2. 条件分支未触发:如果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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 12:27:51