Flutter使用flutter_reactive_ble实现BLE连接重试问题求助
问题分析与解决方案
你的代码核心问题在于connectToDevice函数中,await的是listen()返回的StreamSubscription对象,而非等待连接流程的最终结果。listen()会立即返回订阅对象,函数随即执行return _connected,此时_connected还是初始的false,导致外层connect函数的await根本没等到实际连接结果,循环直接快速执行三次。
要实现等待连接结果后再重试,需要用Completer来包装连接流程,让connectToDevice真正等待到连接成功、超时或出错的明确结果后再返回。
修改后的完整代码
Future<bool> connect(DiscoveredDevice foundDevice) async { var count = 0; var connectionStatus = false; while (!connectionStatus && count < 3) { connectionStatus = await connectToDevice(foundDevice); count++; // 可选:重试前添加短暂延迟,避免频繁重试 if (!connectionStatus && count < 3) { await Future.delayed(const Duration(seconds: 1)); } } return connectionStatus; } static Future<bool> connectToDevice(DiscoveredDevice foundDevice) async { // 取消扫描 _scanStream.cancel(); final completer = Completer<bool>(); StreamSubscription? subscription; try { subscription = flutterReactiveBle.connectToAdvertisingDevice( id: foundDevice.id, withServices: [serviceUuid], prescanDuration: const Duration(seconds: 5), servicesWithCharacteristicsToDiscover: {serviceUuid: [readCharacteristicUuid]}, connectionTimeout: const Duration(seconds: 2), ).listen( (connectionState) { print("Connection Status"); print(connectionState); switch (connectionState.connectionState) { case DeviceConnectionState.connected: _rxCharacteristic = QualifiedCharacteristic( serviceId: serviceUuid, characteristicId: readCharacteristicUuid, deviceId: connectionState.deviceId, ); print(_rxCharacteristic); _connected = true; found_BLE_device = foundDevice; // 连接成功,完成Completer completer.complete(true); break; case DeviceConnectionState.disconnected: print("Disconnected BLE"); _connected = false; // 连接断开,完成Completer返回失败 if (!completer.isCompleted) { completer.complete(false); } break; default: _connected = false; break; } }, onError: (dynamic error) { print("ERROR: $error"); _connected = false; // 出错时完成Completer返回失败 if (!completer.isCompleted) { completer.complete(false); } }, onDone: () { // 流结束但未完成的情况,返回失败 if (!completer.isCompleted) { completer.complete(false); } }, ); // 等待Completer的结果 return await completer.future; } finally { // 无论成功失败,取消订阅避免内存泄漏 subscription?.cancel(); } }
关键修改说明
- 使用Completer:通过
Completer将流的异步事件转换为可等待的Future,确保函数在得到明确的连接结果后才返回。 - 流事件处理:在
connected状态时完成Completer并返回true;在disconnected、错误或流结束时,若Completer未完成则返回false。 - 资源清理:在
finally块中取消流订阅,防止内存泄漏。 - 可选延迟:在重试前添加短暂延迟,避免过于频繁的重试操作影响设备性能。
这样修改后,connect函数中的await connectToDevice()会真正等待连接流程结束,只有当连接结果返回后,才会进入下一次循环判断,实现你需要的“连接成功则退出循环,失败则重试最多3次”的逻辑。
内容的提问来源于stack exchange,提问作者SPP
相关产品推荐
相关产品推荐

