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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 12:30:13