android - CoroutineWorker 中的实时数据观察者
问题描述
我有一个定期执行的 Worker。它连接到 BLE 设备并从中同步数据。连接由观察者完成。doWork 调用 syncRides()。syncRides 创建了一个 observeForever,并开始连接,当连接建立时调用 BleClient.runBleSync()。
我担心的是每 15 分钟(最短 WorkManager 时间)调用一次“observeForever”,并创建未删除的 observeForever。问题是 BleWorker 没有用于创建“BleClient.connectionStatus.observe”而不是“BleClient.connectionStatus.observeForever”的 LifecycleOwner。我的问题是我是否应该担心使用 observeForever 并每 15 分钟触发一次。或者,也许您可以建议更好的选择,例如添加和删除观察者。
此外,在没有 GlobalScope.launch(Dispatchers.Main) 的情况下运行时,会出现此函数无法在后台线程上运行的错误。那么在Worker中运行时Dispatchers.Main是什么意思呢?
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")
}
}
}
}
}
客户端:
object BleClient {
val connectionStatus = MutableLiveData(ConnectionStatus.NOT_CONNECTED)
fun connect(mac: String) {
//do some magic
connectionStatus.postValue(ConnectionStatus.CONNECTED)
}
}
解决方案
我假设该应用程序通过蓝牙连接到另一台设备的任何同步数据。如果我的假设是正确的,首先,您应该将同步过程卸载到前台服务,因为该过程需要很长时间。您仍然可以使用 WorkManager 进行调度。在前台服务中,您应该连接 BLE 并同步数据。为此,有不同的选择。如果您需要使用 observable 来观察连接状态,则应该使用 MutableSharedFlow 而不是 MutableLiveData,这样您就可以使用在 Service 类中创建的生命周期范围来观察变化。但是,在我看来,更好的做法是将您的 connect() 函数转换为可暂停函数。为此,您可以使用 suspendCoroutine 构建器进行转换。此外,如果您同时从不同线程调用连接函数,你必须使用锁来避免多重连接。Kotlin Coroutines 对此有非阻塞锁。将 connect() 函数转换为挂起函数后,您可以以线性方式实现逻辑,这很简单,不需要任何观察。
推荐阅读
- jquery - 仅当条件适用时才选中和取消选中复选框
- javascript - 在 node.js 中使用 Buffer
- json - 如何在 GraphQL cURL POST 请求的 JSON 正文中插入 bash 变量
- javascript - 打字稿在道具中获取子道具
- file-upload - 无法使用 ktor 客户端将文件上传到 ktor 服务器
- html - 在兄弟姐妹上使用 CSS '+' 选择器不起作用
- pip - word2vec 安装失败的轮子无法为使用 PEP 517 且无法直接安装的 word2vec 构建轮子
- angular - 错误:遇到未定义的提供者!通常这意味着你有一个循环依赖(可能是由使用'桶' index.ts 文件引起的
- android - 如何实现网络通话,当用户在另一个通话中并且他的通话不受干扰
- java - 在序列化中追加