android - 重复协程工作者
问题描述
我有一个协程工作者,我想每隔约 1 分钟定期调用它。你将如何继续这样做?
我的工人看起来像这样:
class CloudDataWorker(context: Context, params: WorkerParameters):
CoroutineWorker(context, params) {
companion object {
const val WORK_NAME = "CloudDataWorker"
}
override suspend fun doWork(): Result {
Timber.d("Background worker started.")
val repository = Repository(applicationContext);
return try {
if(repository.getAllJobs().hasActiveObservers()){
Timber.d("Found active listeners on cloud data.")
repository.refreshJobs()
} else {
Timber.d("No active listeners for cloud data found.")
}
Result.success()
} catch (e: HttpException) {
Timber.e("Error during update of cloud data: ${e.message()}")
Result.retry()
}
}
}
解决方案
好吧,这个想法是使用一次性请求(带有初始延迟)来设置工作,并使用observeForever()
来重新设置工作。
Toast
以下是每 5 秒显示一条消息的示例:
private val backgroundScope = CoroutineScope(Dispatchers.Default) //standard background thread
private fun initWork() {
backgroundScope.launch { //setup work in background thread
setupToastShowingWork(0) //no delay at first time
observeToastShowingWork() //observe work state changes
}
}
private fun setupToastShowingWork(delayInSeconds: Long) { //must run in background thread
val constraints = Constraints.Builder().run {
setRequiredNetworkType(NetworkType.UNMETERED) //when using WiFi
build()
}
val oneTimeRequest = OneTimeWorkRequestBuilder<ToastShower>().run { //【for breaking 15 minutes limit we have to use one time request】
setInitialDelay(delayInSeconds, TimeUnit.SECONDS) //customizable delay (interval) time
setConstraints(constraints)
build()
}
WorkManager.getInstance(applicationContext).enqueueUniqueWork( //【must be unique!!】
ToastShower::class.java.simpleName, //work name, use class name for convenient
ExistingWorkPolicy.KEEP, //if new work comes in with same name, discard the new one
oneTimeRequest
)
}
private suspend fun observeToastShowingWork() {
withContext(Dispatchers.Main) { //【must run in Main thread!!】 See below
WorkManager.getInstance(applicationContext).getWorkInfosForUniqueWorkLiveData(ToastShower::class.java.simpleName).observeForever {
if (it[0].state == WorkInfo.State.SUCCEEDED) { //when the work is done
backgroundScope.launch { //prevent from running in Main thread
setupToastShowingWork(5) //every 5 seconds
}
}
}
}
}
演示:https ://youtu.be/7IsQQppKqFs
有用的阅读:
推荐阅读
- corda - Corda - 无法处理包含大量状态的事务
- c - C中的快速图像平滑
- reactjs - 如何就地使用 ANT Design Menu.Item 和 Upload 组件?
- c# - 如何使用 LINQ C# 中的另一个列表过滤列表
- flutter - 你将如何实现一个 BLoC 来发出所有 CRUD 调用的状态?
- javascript - 将 react.js 连接到 Google Collab
- django - Django消息未显示在重定向上,仅呈现
- javascript - 将代码片段转换为 Sphinx 中的 HTML 代码?
- javascript - Vue jest 测试当前目标父级点击时有类(通过v-for添加)
- file-upload - JMETER:多部分/表单数据请求 - 无法使用 jmeter 上传任何文件类型