【问题标题】:Repeating coroutine worker重复协程工作者
【发布时间】:2021-04-24 09:27:42
【问题描述】:

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

【问题讨论】:

    标签: android kotlin


    【解决方案1】:

    嗯,这个想法是使用 One Time 请求(带有初始延迟)来设置工作,并使用observeForever() 重新设置工作。

    以下是每 5 秒显示一条 Toast 消息的示例:

    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


    有用的阅读:

    【讨论】:

      【解决方案2】:

      你不能。 PeriodicWork see the docs here 的最小运行间隔为 15 分钟。

      如果您的应用程序在前台,我建议您将循环与协程一起使用并利用Kotlin Flows

      class YourViewModel(val repo: YourRepo) : ViewModel() {
      
          val yourJobOffers = 
              flow {
                  while(true) {
                      emit(repo.fetchJobs())
                      delay(1000 * 60)
                  }
              }
              .launchIn(Dispatchers.IO)
      }
      

      【讨论】:

        猜你喜欢
        • 2014-03-10
        • 2011-09-04
        • 1970-01-01
        • 1970-01-01
        • 2016-08-02
        • 2019-05-30
        • 2021-07-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多