首页 > 解决方案 > 重复协程工作者

问题描述

我有一个协程工作者,我想每隔约 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()
        }
    }
}

标签: androidkotlin

解决方案


好吧,这个想法是使用一次性请求(带有初始延迟)来设置工作,并使用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


有用的阅读:


推荐阅读