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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 09:25:34