Andy Cass
Andy Cass

Reputation: 446

WorkManager not being replaced using ExistingPeriodicWorkPolicy.REPLACE

Calling ExistingPeriodicWorkPolicy.REPLACE just starts another workManager it doesn't replace the other one, multiple workManagers are running when triggered not replaced

val constraints = Constraints.Builder()
        .setRequiredNetworkType(NetworkType.CONNECTED)
        .build()

    val workRequest = PeriodicWorkRequestBuilder<SongsWorker>(1, TimeUnit.DAYS)
            .addTag(TAG)
            .setConstraints(constraints)
            .build()

    WorkManager.getInstance(mContext).enqueueUniquePeriodicWork(
        TAG, ExistingPeriodicWorkPolicy.REPLACE, workRequest)

The log suggests the work manager is at least asking to be cancelled, but the execution continues

I/WM-WorkerWrapper: Work [ id=6ed5487e-5d7b-4db5-a4c5-c22c562567e5, tags={ 
workerManagers.songs.SongsWorkerManager$SongsWorker } ] was cancelled
java.util.concurrent.CancellationException: Task was cancelled.
    at androidx.work.impl.utils.futures.AbstractFuture.cancellationExceptionWithCause(AbstractFuture.java:1184)
    at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:514)
    at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:475)
    at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:300)
    at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:923)

I have attached a listener to the work manager and the log is

2021-04-30 20:40:54.318 17868-17868 Fragment: ID = 9f8b3165-fc75-4f9a-ba39-41c2dc6a17b3
2021-04-30 20:40:54.408 17868-17868 Fragment: ID = 9f8b3165-fc75-4f9a-ba39-41c2dc6a17b3
2021-04-30 20:40:54.427 17868-17868 Fragment: ID = 9f8b3165-fc75-4f9a-ba39-41c2dc6a17b3

The listener is:

val instance = WorkManager.getInstance(requireContext())
  instance.getWorkInfosForUniqueWorkLiveData(SongsWorkerManager.TAG)
        .observe(viewLifecycleOwner) { workInfo ->
            workInfo.forEach {
                Log.d(TAG, "ID = ${it.id}")
            }
        }

After triggering the work manager 3 times, 3 identical work managers are running rather then being replaced.

Upvotes: 1

Views: 981

Answers (2)

Andy Cass
Andy Cass

Reputation: 446

If anyone else is having trouble stopping a work manager with ExistingPeriodicWorkPolicy.REPLACE, call

if (isStopped) return Result.success()

inside doWork() and you will get the behaviour you expect.

Thanks to

WorkManager.getInstance().cancelAllWorkByTag() not stopping the periodic job

""One way to do this is to put a few checks in your doWork method to check if the worker has been cancelled, by calling isStopped(). If isStopped is true, return from the method with a Result instead of continuing with the rest of the work.""

and

How to make sure that WorkManager cancels my Worker?

Upvotes: 1

Navjot
Navjot

Reputation: 1294

The above logs are not justifying that the old workers are not canceled. You can add the following observer to check the current status of all the workers through WorkInfo

WorkManager.getInstance(context).getWorkInfosByTagLiveData(TAG)
            .observe(lifecycleOwner, { workInfo ->
                workInfo.forEach { 
                    println("Worker Info -> $it")
                }
            })

Upvotes: 1

Related Questions