Flutter OTP自动填充后无法验证 求验证按钮事件实现代码
问题根因
- 自动填充后校验失败的核心原因:
sms_autofill监听到短信验证码后,仅向输入框绑定的TextEditingController写入值完成UI填充,该操作不会触发输入组件的onChanged回调,状态类中存储OTP值的变量未同步更新,点击按钮时读取到的仍是空值/初始值,无法通过Firebase Auth校验。 - 手动输入场景下每次字符输入都会触发
onChanged回调,状态变量与输入框内容实时同步,因此校验流程正常。
Verify OTP按钮onPressed正确实现
前置配置(必须做,否则自动填充值不同步)
先在短信监听逻辑中补全状态同步代码,放在页面initState生命周期中执行:
late TextEditingController otpController; String currentOtp = ""; bool isLoading = false; @override void initState() { super.initState(); otpController = TextEditingController(); _listenSmsCode(); } void _listenSmsCode() async { await SmsAutoFill().listenForCode; SmsAutoFill().code.listen((code) { setState(() { // 填充输入框的同时同步更新状态变量 otpController.text = code; currentOtp = code; }); }); }
按钮点击事件完整逻辑
ElevatedButton( onPressed: () async { // 收起键盘 FocusScope.of(context).unfocus(); // 核心:直接从controller取最新值做兜底,不依赖单独存储的状态变量 final inputOtp = otpController.text.trim(); // 基础格式校验 if (inputOtp.length != 6) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("请输入完整6位验证码")) ); return; } setState(() { isLoading = true; }); try { // 复用手动输入页的Firebase Auth校验逻辑,不要做任何修改 PhoneAuthCredential credential = PhoneAuthProvider.credential( verificationId: widget.verificationId, smsCode: inputOtp ); await FirebaseAuth.instance.signInWithCredential(credential); // 校验成功跳转 if (mounted) { Navigator.pushReplacementNamed(context, '/home'); } } on FirebaseAuthException catch (e) { String errorMsg = "验证失败,请重试"; if (e.code == 'invalid-verification-code') { errorMsg = "验证码无效,请检查后重新输入"; } else if (e.code == 'session-expired') { errorMsg = "验证码已过期,请重新获取"; } if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(errorMsg)) ); } } finally { if (mounted) { setState(() { isLoading = false; }); } } }, child: isLoading ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white) ) : const Text("Verify OTP"), )
避坑注意项
- 页面销毁时必须注销短信监听、释放controller,避免内存泄漏:
@override void dispose() { SmsAutoFill().unregisterListener(); otpController.dispose(); super.dispose(); }
- 如果使用
pinput/pin_code_fields等第三方验证码输入组件,直接绑定上述otpController即可,自动填充时组件会自动同步内容,无需额外处理光标位置。 - 所有输入值校验统一在按钮点击时从controller读取,不要完全依赖
onChanged回调传值,可覆盖所有自动填充、粘贴等非手动输入场景的值不同步问题。
内容的提问来源于stack exchange,提问作者sr2k23
相关产品推荐
相关产品推荐

