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

如何在Ble回调执行后从ViewModel的Kotlin函数返回结果?

问题分析

你的代码里,connectToCharger是同步函数,但蓝牙设备连接是异步操作——scanForDevicesAndConnectTohomeCharger会立刻执行完毕,函数直接返回初始的NoDataFailure,而onBleDeviceStateChange回调要等到蓝牙状态变化时才会触发,这时候函数早就返回了,回调里修改的result变量对返回值没有任何影响。

要实现"等待回调触发后再返回结果",有两种常用的解决方案,适配ViewModel的使用场景:


方案一:用Kotlin协程+CompletableDeferred(推荐)

把函数改成挂起函数,通过CompletableDeferred等待异步回调的结果,适合需要直接获取返回值的场景:

// 改成suspend挂起函数
private suspend fun connectToCharger(activity: Activity): NoDataResult {
    val deferred = CompletableDeferred<NoDataResult>()

    blufiHelper.scanForDevicesAndConnectTohomeCharger(
        activity,
        "homewifi1",
        object : BleStateCallback {
            override fun updateMessage(message: String) {
                Timber.d("xxx VM $message")
                // 这里可以保留LiveData更新UI逻辑
                // _connectMessage.value = message
            }

            override fun onBleDeviceStateChange(state: BleDeviceState) {
                Timber.d("xxx VM onBleDeviceStateChange $state")
                val result = when (state) {
                    BleDeviceState.Connected -> NoDataSuccess
                    BleDeviceState.Disconnected -> NoDataFailure(RuntimeException("连接失败:设备断开"))
                    else -> NoDataFailure(RuntimeException("连接失败:未知状态"))
                }
                // 把结果传递给deferred
                deferred.complete(result)
            }
        })

    // 可选:添加超时处理,避免无限等待
    return withContext(Dispatchers.IO) {
        withTimeoutOrNull(30_000) { // 30秒超时
            deferred.await()
        } ?: NoDataFailure(RuntimeException("连接超时"))
    }
}

调用方式

在ViewModel的协程作用域里调用(比如viewModelScope):

fun startChargerConnection(activity: Activity) {
    viewModelScope.launch {
        val result = connectToCharger(activity)
        // 处理结果,比如用LiveData通知UI
        _connectResult.value = result
    }
}

方案二:用LiveData直接传递结果

如果不需要函数返回值,而是让UI层观察结果变化,可以直接用LiveData:

// 在ViewModel里定义LiveData
private val _connectResult = MutableLiveData<NoDataResult>()
val connectResult: LiveData<NoDataResult> = _connectResult

private fun connectToCharger(activity: Activity) {
    blufiHelper.scanForDevicesAndConnectTohomeCharger(
        activity,
        "homewifi1",
        object : BleStateCallback {
            override fun updateMessage(message: String) {
                Timber.d("xxx VM $message")
                // 可选:用LiveData更新连接过程消息
                // _connectMessage.value = message
            }

            override fun onBleDeviceStateChange(state: BleDeviceState) {
                Timber.d("xxx VM onBleDeviceStateChange $state")
                val result = when (state) {
                    BleDeviceState.Connected -> NoDataSuccess
                    BleDeviceState.Disconnected -> NoDataFailure(RuntimeException("连接失败:设备断开"))
                    else -> NoDataFailure(RuntimeException("连接失败:未知状态"))
                }
                // 发布结果到LiveData,用postValue确保主线程更新
                _connectResult.postValue(result)
            }
        })
}

UI层观察结果

viewModel.connectResult.observe(this) { result ->
    when(result) {
        is NoDataSuccess -> // 处理连接成功逻辑
        is NoDataFailure -> // 处理连接失败逻辑,比如显示错误提示
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 13:21:34