Flutter PIN码创建页面:重复输入后无法跳转首页问题求助
PIN码页面无法跳转的问题分析与修复
核心问题
1. SharedPreferences存储Key不统一
代码里混用了pinCode和pinCod(拼写少了末尾的'e')两个Key,导致存储和读取的数据完全不对应,永远读不到正确的PIN值。
2. 异步函数调用错误
sharedPrefsGet()是异步函数,返回的是Future<int?>对象,直接用==和字符串value比较时,实际是在对比Future对象和字符串,永远不会相等,必须用await获取实际值后再做判断。
3. 业务逻辑完全颠倒
在onCompleted回调里,逻辑顺序混乱:
- 本地无PIN时,应该存储用户输入的PIN并完成创建流程,而不是跳回当前页面;
- 本地已有PIN时,应该验证输入值和存储值是否一致,一致才跳转首页,不一致要提示错误。
4. 冗余代码强制跳转
原代码onCompleted末尾的context.go('/createPinCode')会强制刷新当前页面,直接覆盖了之前的跳转逻辑,导致无论验证是否成功都会回到创建页。
修复后的代码示例
class CreatePinCode extends StatefulWidget { @override _CreatePinCodeState createState() => _CreatePinCodeState(); } class _CreatePinCodeState extends State<CreatePinCode> { final TextEditingController _controller = TextEditingController(); var pinCode; // 统一使用正确的Key:pinCode Future<bool> sharedPrefsSet(int pin) async { final prefs = await SharedPreferences.getInstance(); return await prefs.setInt('pinCode', pin); } Future<int?> sharedPrefsGet() async { final prefs = await SharedPreferences.getInstance(); final storedPin = prefs.getInt('pinCode'); print(storedPin); return storedPin; } late final Future<int?> future = sharedPrefsGet(); @override void initState() { super.initState(); sharedPrefsGet(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: ConfigColor.background, body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ FutureBuilder( future: future, builder: (context, snapshot) => snapshot.hasData ? Text('已设置PIN码') : Text('未设置PIN码'), ), Padding( padding: const EdgeInsets.all(100), child: SizedBox( height: 70, child: Center( child: PinCodeTextField( controller: _controller, mainAxisAlignment: MainAxisAlignment.spaceAround, obscuringWidget: Container( width: 15, height: 15, decoration: BoxDecoration( color: ConfigColor.green, shape: BoxShape.circle, ), ), appContext: context, length: 4, onChanged: (value) { print(value); }, pinTheme: PinTheme( shape: PinCodeFieldShape.box, borderRadius: BorderRadius.circular(50), fieldHeight: 15, fieldWidth: 15, activeColor: ConfigColor.green, inactiveColor: Colors.white.withOpacity(0.3), disabledColor: Colors.white.withOpacity(0.3), ), onCompleted: (values) async { final inputPin = int.parse(values); final storedPin = await sharedPrefsGet(); if (storedPin == null) { // 本地无PIN,存储后跳转首页 await sharedPrefsSet(inputPin); context.go('/home'); } else { // 本地已有PIN,验证匹配性 if (storedPin == inputPin) { context.go('/home'); } else { // 验证失败,提示错误并清空输入 log('PIN码不匹配!'); _controller.clear(); } } }, ), ), ), ), NumPad( buttonSize: 65, buttonColor: ConfigColor.background, iconColor: Colors.deepOrange, controller: _controller, delete: () { if (_controller.text.isNotEmpty) { _controller.text = _controller.text.substring(0, _controller.text.length - 1); } }, onSubmit: () { debugPrint('Your code: ${_controller.text}'); showDialog( context: context, builder: (_) => AlertDialog( content: Text( "您的PIN码是 ${_controller.text}", style: const TextStyle(fontSize: 30), ), ), ); }, ), ], ), ); } }
额外优化建议
- 拆分页面:把PIN创建和PIN验证拆成两个独立页面,逻辑更清晰,避免单个页面同时处理两种业务;
- 增强错误反馈:验证失败时用弹窗或SnackBar给用户明确提示;
- 输入校验:添加数字输入校验,防止
int.parse()抛出异常; - 优化FutureBuilder:
future变量在initState初始化即可,避免每次build都重复执行异步读取操作。
内容的提问来源于stack exchange,提问作者Daniil
相关产品推荐
相关产品推荐

