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
相关产品推荐
相关产品推荐

