Search code examples
androidkotlinandroid-workmanager

How to change periodic work request period without it running immediately using WorkManager?


val request = PeriodicWorkRequestBuilder<FooWorker>(1, TimeUnit.DAYS).build()
WorkManager.getInstance().enqueueUniquePeriodicWork(
    "FOO",
    ExistingPeriodicWorkPolicy.REPLACE,
    request
)

The code above is ran in onCreate of Application to ensure the request is enqueued. However, this will cause a problem where the FooWorker will run every time user start the application because ExistingPeriodicWorkPolicy.REPLACE cancel previous work and enqueue new work which cause it run immediately.

If we change to ExistingPeriodicWorkPolicy.KEEP, we will not able to replace the work even the period or the worker is changed.

Is there a way to replace the request after the current one is running?

For example, origin request run a 1 time per day and the new request is 1 time per hour. After the next origin request is ran, then replace it with new request.


Solution

  • There is no way to do exactly what you want with periodic work in a clean way.

    However, there's absolutely no need to use periodic work itself. The same structure can be easily accomplished by scheduling the next WorkRequest at the end of your doWork method, right before returning Result.SUCCESS:

    fun doWork(): Result {
      reallyDoWork()
      // Now schedule the next "periodic" work
      val request = OneTimeWorkRequestBuilder<FooWorker>().build()
      WorkManager.getInstance().enqueueUniqueWork(
        "FOO",
        ExistingWorkPolicy.REPLACE,
        request
      )
      return Result.SUCCESS
    }
    

    With this setup, your onCreate() of Application can safely use ExistingWorkPolicy.KEEP to avoid rescheduling work if you already have a WorkRequest queued up and when that queued up work fires, the next WorkRequest will be queued up with the appropriate new period.