WorkManager beginUniqueWork doesn't work as expected
Asked Answered
R

2

12

Currently, I'm using WorkManager 1.0.0-alpha02.

def work_version = "1.0.0-alpha02"
implementation "android.arch.work:work-runtime:$work_version" // use -ktx for Kotlin
// optional - Firebase JobDispatcher support
implementation "android.arch.work:work-firebase:$work_version"

I have no problem to execute background worker, by using the following code, when the app quit.

Use enqueue, work as expected

OneTimeWorkRequest oneTimeWorkRequest =
        new OneTimeWorkRequest.Builder(SyncWorker.class)
                .addTag(SyncWorker.TAG)
                .build();

WorkManager workManager = WorkManager.getInstance();

workManager.enqueue(oneTimeWorkRequest);

Since, I would like to avoid more than one SyncWorker running at the same time. I try to use

Use beginUniqueWork, doesn't work

OneTimeWorkRequest oneTimeWorkRequest =
        new OneTimeWorkRequest.Builder(SyncWorker.class)
                .addTag(SyncWorker.TAG)
                .build();

WorkManager workManager = WorkManager.getInstance();

workManager.beginUniqueWork(
        SyncWorker.TAG,
        ExistingWorkPolicy.REPLACE,
        oneTimeWorkRequest
);

SyncWorker is not running at all.

May I know what step I had missed out? Thank you.

Refractor answered 2/6, 2018 at 13:42 Comment(0)
E
25

beginUniqueWork() returns a WorkContinuation object. You need to call enqueue on that WorkContinuation to actually enqueue it with WorkManager:

workManager.beginUniqueWork(
    SyncWorker.TAG,
    ExistingWorkPolicy.REPLACE,
    oneTimeWorkRequest
).enqueue();
Entoblast answered 2/6, 2018 at 14:53 Comment(8)
Thanks. I manage to make it run now. I test using ExistingWorkPolicy.KEEP, and purposely make the worker doing infinity while loop with sleep. No more than 1 worker running. However, if I explicitly perform cancelAllWorkByTag(SyncWorker.TAG) and cancelUniqueWork(SyncWorker.TAG) before 2nd enqueue, I notice previous worker will not be killed. Yet, 2nd worker is allowed to run. This makes 2 workers running simultaneously. Does this mean, if we are using beginUniqueWork, we shouldn't call cancelAllWorkByTag and cancelUniqueWork?Refractor
As per the documentation cancelation is best effort. This applies equally for all types of WorkEntoblast
Ok. Thanks. Initially I thought if the cancel operation is not success, beginUniqueWork will not start another worker. Seem like my assumption is wrong.Refractor
There's additional cancelation related APIs that are to be added in alpha03. Your Worker would still need to check for cancellation though to end its work early if cancelledEntoblast
Thanks. Do you know when will there be 1.0 version? As, we plan to release some code to production based on WorkManager. Would be nice to know when is the 1.0 be ready.Refractor
There's already a number of apps that have shipped WorkManager to production. Alpha for Architecture Components is more about API stability than runtime stability, but YMMV, test thoroughly, etcEntoblast
By the way, to really ensure there's single Worker running, is using an additional synchronized a good way? - gist.github.com/yccheok/b165c483788b09830b3b28148ab7d4c0Refractor
Seems reasonableEntoblast
S
13

The answer from @ianhanniballake is of course helpful and correct, but I thought I'd point out that (with a fast-evolving API) there is a new enqueueUniqueWork() method so I guess the OP could now use:

workManager.enqueueUniqueWork(
    SyncWorker.TAG,
    ExistingWorkPolicy.REPLACE,
    oneTimeWorkRequest
);
Saied answered 17/12, 2018 at 8:34 Comment(1)
I have a similar code, however my Worker is not called, why would that be?Naldo

© 2022 - 2024 — McMap. All rights reserved.