Flutter使用flutter_reactive_ble时BLE连接等待及批量断连问题
循环执行BLE操作无等待问题修复
问题根因
- onPressed回调未声明
async,导致内部await逻辑不生效,for循环同步执行完毕不会等待异步操作完成 await与then混用导致等待逻辑混乱,无法正确等待连接、写入、断开全链路完成- 若你封装的
connect方法未适配flutter_reactive_ble的连接状态流特性,会直接返回未完成的Future导致提前结束等待
修复代码
调整IconButton回调逻辑
IconButton( // 其余原有配置保持不变 onPressed: () async { // 必须声明async才支持内部await for (String deviceId in deviceIdList) { try { // 串行等待单设备全链路操作完成,再执行下一个设备 await Provider.of<BleDeviceConnector>(context, listen: false).connect(deviceId); await loadStuff(context); await Provider.of<BleDeviceConnector>(context, listen: false).disconnect(deviceId); } catch (e) { print("设备$deviceId操作失败:$e"); // 若需要出错后中断流程,此处加break即可 } } } )
适配connect方法封装(针对flutter_reactive_ble原生流特性)
flutter_reactive_ble的connectToDevice返回的是连接状态流,需封装为等待连接成功才完成的Future:
import 'dart:async'; import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; class BleDeviceConnector { final FlutterReactiveBle _ble = FlutterReactiveBle.instance; // 存储所有设备的连接订阅,用于后续断连 final Map<String, StreamSubscription<ConnectionStateUpdate>> _connSubs = {}; Future<void> connect(String deviceId) async { final completer = Completer<void>(); // 重复连接前先清理旧订阅 if (_connSubs.containsKey(deviceId)) { await _connSubs[deviceId]?.cancel(); _connSubs.remove(deviceId); } final sub = _ble.connectToDevice(id: deviceId).listen( (state) { if (state.connectionStatus == DeviceConnectionStatus.connected) { if (!completer.isCompleted) completer.complete(); } }, onError: (e) { if (!completer.isCompleted) completer.completeError(e); _connSubs.remove(deviceId); }, ); _connSubs[deviceId] = sub; await completer.future; } }
批量断连仅首台设备生效问题修复
问题根因
自定义的BleDeviceConnector未存储多设备的连接订阅,仅保存了单个设备的订阅实例,每次新设备连接会覆盖旧订阅,导致断连时只能拿到第一个/最后一个设备的订阅,其余设备无法正常释放连接。
修复代码
改造disconnect方法封装
Future<void> disconnect(String deviceId) async { if (_connSubs.containsKey(deviceId)) { // 取消对应设备的连接订阅,触发底层断连 await _connSubs[deviceId]?.cancel(); _connSubs.remove(deviceId); } // 可选:清理GATT缓存避免后续连接冲突 await _ble.clearGattCache(deviceId); }
批量断连调用逻辑
// 遍历已连接设备列表串行断连即可 onPressed: () async { for (String deviceId in connectedDeviceIdList) { try { await Provider.of<BleDeviceConnector>(context, listen: false).disconnect(deviceId); // 可选:添加100ms延迟,给底层BLE栈留处理时间,提升稳定性 await Future.delayed(const Duration(milliseconds: 100)); } catch (e) { print("设备$deviceId断开失败:$e"); } } }
额外注意事项
- 所有BLE操作尽量串行执行,并发操作容易触发系统BLE栈的底层bug,导致应用无响应
- 不需要连接设备时及时清理订阅,避免内存泄漏和后续操作冲突
- Android平台批量操作BLE设备时,需确认已申请
ACCESS_FINE_LOCATION、BLUETOOTH_CONNECT、BLUETOOTH_SCAN权限,避免权限限制导致操作失败
内容的提问来源于stack exchange,提问作者AmericanMade
相关产品推荐
相关产品推荐

