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

基于RXAndroidBLE监听蓝牙连接状态及UI适配问题

解决BLE连接状态监听与UI更新问题

首先得说,你代码里的核心问题是过早调用了disposable.dispose()——这行代码会立刻终止establishConnection的订阅,导致连接还没建立就被取消,所以内部的println和状态监听代码根本没机会执行。另外还有嵌套订阅、不必要的null判断这些小问题,我帮你一步步梳理并给出正确实现:

先搞懂所有BLE连接状态

RxBleConnection.RxBleConnectionState是个枚举类,包含4种状态,你需要全部覆盖来适配UI:

  • DISCONNECTED:设备未连接
  • CONNECTING:正在连接中
  • CONNECTED:已成功连接
  • DISCONNECTING:正在断开连接

正确的实现方式

方案1:分开监听状态与建立连接(直观易维护)

这种方式把状态监听和连接操作分开,逻辑更清晰:

val rxBleClient = RxBleClient.create(this.context!!)
val bleDevice = rxBleClient.getBleDevice("34:81:F4:3C:2D:7B")

// 1. 先订阅连接状态变化,确保能捕获所有状态
val stateDisposable = bleDevice.observeConnectionStateChanges()
    // 必须切换到主线程更新UI,否则会报错
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ connectionState ->
        println("Connection State: $connectionState")
        // 用when匹配所有状态,更新对应UI
        when(connectionState) {
            RxBleConnection.RxBleConnectionState.CONNECTED -> {
                enableBluetooth.setBackgroundResource(R.drawable.bluetooth_on)
                deviceConnected.setText(R.string.connected_to_hooplight)
            }
            RxBleConnection.RxBleConnectionState.CONNECTING -> {
                deviceConnected.setText(R.string.connecting_to_hooplight)
                // 可以加个加载动画之类的
            }
            RxBleConnection.RxBleConnectionState.DISCONNECTING -> {
                deviceConnected.setText(R.string.disconnecting_from_hooplight)
            }
            RxBleConnection.RxBleConnectionState.DISCONNECTED -> {
                enableBluetooth.setBackgroundResource(R.drawable.bluetooth_off)
                deviceConnected.setText(R.string.connect_to_hooplight)
            }
        }
    }, { throwable ->
        Log.d("State Error", "监听状态失败: ${throwable.message}")
    })

// 2. 建立BLE连接(autoConnect=true)
val connectionDisposable = bleDevice.establishConnection(true)
    .subscribe({ rxBleConnection ->
        // 连接成功后,这里可以执行GATT操作(比如读写特征)
        Log.d("BLE", "连接成功,可进行GATT通信")
    }, { throwable ->
        Log.d("Connection Error", "连接失败: ${throwable.message}")
    })

// 3. 关键!在合适的时机销毁订阅(比如页面销毁时)
override fun onDestroy() {
    super.onDestroy()
    stateDisposable.dispose()
    connectionDisposable.dispose()
}

方案2:用RxJava操作符组合流(响应式风格)

如果更习惯RxJava的链式调用,可以用flatMap把连接和状态监听合并:

val rxBleClient = RxBleClient.create(this.context!!)
val bleDevice = rxBleClient.getBleDevice("34:81:F4:3C:2D:7B")

val combinedDisposable = bleDevice.establishConnection(true)
    .flatMap { connection ->
        // 连接成功后,同时监听状态变化,先发射一次已连接状态
        bleDevice.observeConnectionStateChanges()
            .startWithItem(RxBleConnection.RxBleConnectionState.CONNECTED)
    }
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ connectionState ->
        println("Connection State: $connectionState")
        // 同样用when处理UI更新,代码同方案1
        when(connectionState) {
            RxBleConnection.RxBleConnectionState.CONNECTED -> {
                enableBluetooth.setBackgroundResource(R.drawable.bluetooth_on)
                deviceConnected.setText(R.string.connected_to_hooplight)
            }
            RxBleConnection.RxBleConnectionState.CONNECTING -> {
                deviceConnected.setText(R.string.connecting_to_hooplight)
            }
            RxBleConnection.RxBleConnectionState.DISCONNECTING -> {
                deviceConnected.setText(R.string.disconnecting_from_hooplight)
            }
            RxBleConnection.RxBleConnectionState.DISCONNECTED -> {
                enableBluetooth.setBackgroundResource(R.drawable.bluetooth_off)
                deviceConnected.setText(R.string.connect_to_hooplight)
            }
        }
    }, { throwable ->
        Log.d("BLE Error", "操作失败: ${throwable.message}")
    })

// 页面销毁时清理资源
override fun onDestroy() {
    super.onDestroy()
    combinedDisposable.dispose()
}

几个重要注意事项

  • 绝对不能提前调用dispose():这是你最初代码不执行println的核心原因——dispose()会立刻取消订阅,连接流程直接终止。必须在不需要连接时(比如页面关闭、用户主动断开)再调用。
  • UI更新必须在主线程:RxJava默认可能在子线程发射事件,所以一定要加observeOn(AndroidSchedulers.mainThread()),否则会抛出UI线程异常。
  • 覆盖所有枚举状态:不要漏掉CONNECTING和DISCONNECTING,否则用户会看不到连接过程中的状态反馈,体验不好。
  • 错误处理不能少:每个subscribe都要处理错误回调,避免未捕获异常导致崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:36:34