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

Flutter技术问询:修改flutter_reactive_ble_example的device_list.dart时,如何实现密码错误时重新弹出输入密码的showDialog

嘿,我来帮你搞定密码错误时重新提示输入的问题!你的需求很明确——当蓝牙模块返回密码验证失败时,再次弹出密码输入框,直到用户输入正确密码为止对吧?咱们可以通过把密码验证逻辑封装成循环请求的异步函数来实现,这样代码更清晰也更可靠。

首先,咱们把密码输入和验证的逻辑拆成两个单独的函数,让代码结构更清爽:

// 循环请求密码直到输入正确
Future<String> _requestPasswordUntilCorrect(BuildContext context) async {
  while (true) {
    // 弹出密码输入弹窗
    final password = await showDialog<String>(
      context: context,
      barrierDismissible: false,
      builder: (_) {
        String userInput = "";
        return AlertDialog(
          title: const Text("Enter Password"),
          content: TextField(
            onChanged: (value) => userInput = value,
            obscureText: true, // 给密码框加个隐藏效果,更符合使用场景
            decoration: const InputDecoration(hintText: "请输入蓝牙设备密码"),
          ),
          actions: [
            ElevatedButton(
              child: const Text('确认'),
              onPressed: () => Navigator.of(_).pop(userInput),
            ),
          ],
        );
      },
    );

    if (password == null) {
      // 处理用户意外关闭弹窗的情况,这里可以根据需求调整
      throw Exception("密码输入已取消");
    }

    // 发送密码并验证是否正确
    final isCorrect = await _validatePasswordWithDevice(password);

    if (isCorrect) {
      // 密码正确,返回结果
      return password;
    } else {
      // 密码错误,先提示用户,然后继续循环
      if (mounted) {
        await showDialog(
          context: context,
          builder: (_) => AlertDialog(
            title: const Text("验证失败"),
            content: const Text("密码错误,请重新输入!"),
            actions: [
              ElevatedButton(
                child: const Text('确定'),
                onPressed: () => Navigator.of(_).pop(),
              ),
            ],
          ),
        );
      }
    }
  }
}

// 和蓝牙设备交互验证密码
Future<bool> _validatePasswordWithDevice(String password) async {
  try {
    // 订阅特征获取设备响应
    final responseStream = ble.subscribeToCharacteristic(characteristic);
    
    // 发送密码到设备(注意编码格式要和设备端匹配,这里用utf8示例)
    await ble.writeCharacteristicWithoutResponse(
      characteristic,
      value: utf8.encode(password),
    );

    // 等待设备返回结果,设置超时避免无限等待
    final response = await responseStream.first.timeout(
      const Duration(seconds: 5),
      onTimeout: () => throw Exception("验证超时,请检查设备连接"),
    );

    // 用完后取消订阅,防止内存泄漏
    await responseStream.cancel();

    // 根据设备返回值判断,这里假设返回1代表密码正确
    return response == 1;
  } catch (e) {
    // 处理异常,比如设备断开等情况
    debugPrint("密码验证出错: $e");
    return false;
  }
}

接下来,把原来onTap里的逻辑改成调用这个函数,同时修正你代码里的小问题(比如tile应该是device):

onTap: () async {
  // 停止扫描
  widget.stopScan();
  // 连接设备
  await widget.deviceConn.connect(device.id);

  try {
    // 循环获取正确密码
    final correctPassword = await _requestPasswordUntilCorrect(context);
    // 将正确密码传回上一页
    Navigator.of(context).pop(correctPassword);
  } catch (e) {
    // 处理取消或异常情况
    if (mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text(e.toString())),
      );
    }
  }
},

最后提醒你几个关键细节:

  • 密码的编码格式要和你的蓝牙模块要求一致,比如有的设备用ASCII或者十六进制,要调整utf8.encode这部分
  • 超时时间可以根据你的设备响应速度调整
  • 每次验证后取消BLE订阅,防止内存泄漏

这样修改后,就能实现密码错误时自动重新弹出输入框的功能啦!

内容的提问来源于stack exchange,提问作者vontdeux

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 17:07:48