首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CoroutineWorker中的实时数据观察者

CoroutineWorker中的实时数据观察者
EN

Stack Overflow用户
提问于 2021-08-01 08:03:28
回答 1查看 321关注 0票数 1

我有一个定期执行的Worker。它连接到BLE设备并从该设备同步数据。连接是由观察者完成的。调用syncRides()的doWork。syncRides创建一个observeForever,并在建立连接时启动连接,调用BleClient.runBleSync()。

我担心的是每隔15分钟调用一次的" observeForever“(最短的WorkManager时间),并创建未删除的observeForever。问题是BleWorker没有LifecycleOwner来创建"BleClient.connectionStatus.observe“而不是"BleClient.connectionStatus.observeForever”。我的问题是,我是否应该关注使用observeForever并每15分钟触发一次。或者你可以建议更好的选项,比如添加和删除观察者。

此外,在没有GlobalScope.launch(Dispatchers.Main)的情况下运行时,会出现此函数无法在后台线程上运行的错误。那么当在Worker中运行时,Dispatchers.Main意味着什么呢?

代码语言:javascript
复制
class BleWorker(appContext: Context, workerParams: WorkerParameters) : CoroutineWorker(appContext, workerParams) {

override suspend fun doWork(): Result {

    return try {
        try {
            RLog.d("Run work manager")
            syncRides()
            val output: Data = workDataOf("KEY_RESULT" to 1)
            Result.success(output)
        } catch (e: Exception) {
            RLog.d("exception in doWork ${e.message}")
            Result.failure()
        }
    } catch (e: Exception) {
        RLog.d("exception in doWork ${e.message}")
        Result.failure()
    }
}


private suspend fun syncRides() {

    GlobalScope.launch(Dispatchers.Main) {

        val bleDevice = SharedPreferenceHelper.getBleMac()
        if (bleDevice != null && BleClient.connectionStatus.value == BleClient.ConnectionStatus.NOT_CONNECTED) {
            BleClient.connect(bleDevice)
        }

        BleClient.connectionStatus.observeForever {
            RLog.d("Observing $it")

            when (it) {
                BleClient.ConnectionStatus.CONNECTED -> {
                    GlobalScope.launch(Dispatchers.IO) {
                        RLog.d("Running sync")
                        BleClient.runBleSync()
                    }
                }
                else -> {
                    RLog.d("No status")
                }
            }
        }
    }
}

BleClient:

代码语言:javascript
复制
 object BleClient {

 val connectionStatus = MutableLiveData(ConnectionStatus.NOT_CONNECTED)

 fun connect(mac: String) {
//do some magic         
 connectionStatus.postValue(ConnectionStatus.CONNECTED)
 }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-09 15:23:23

我假设应用程序连接到蓝牙上的另一个设备上的任何同步数据.如果我的假设是正确的,首先,您应该将同步过程卸载到前台服务,因为该过程将花费很长时间。不过,您仍然可以使用WorkManager进行调度。在前台服务中,您应该连接BLE和同步数据。为此,有不同的选择。如果您需要使用observable来观察连接状态,则应该使用MutableSharedFlow而不是MutableLiveData,这样您就可以观察在Service类中创建的生命周期范围内的更改。然而,在我看来,更好的做法是将connect()函数转换为可挂起的函数。为此,您可以使用suspendCoroutine构建器进行转换。另外,如果你同时从不同的线程调用connect函数,你必须使用lock来避免多个连接。Kotlin Coroutines为此提供了非阻塞锁。在将connect()函数转换为suspend函数之后,您可以以线性方式实现您的逻辑,这很容易,并且不需要任何类型的观察。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68608561

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档