WorkManager allows you to create and enqueue a chain of work that specifies multiple dependent tasks, and defines what order they should run in. This is particularly useful when you need to run several tasks in a particular order.
To create a chain of work, you can use WorkManager.beginWith(OneTimeWorkRequest)
or WorkManager.beginWith(List<OneTimeWorkRequest>)
, which return an instance of WorkContinuation
.
A WorkContinuation
can then be used to add dependent OneTimeWorkRequest
s usingWorkContinuation.then(OneTimeWorkRequest)
or WorkContinuation.then(List<OneTimeWorkRequest>)
.
Every invocation of the WorkContinuation.then(...)
, returns a new instance of WorkContinuation
. If you add a List
of OneTimeWorkRequest
s, these requests can potentially run in parallel.
Finally, you can use the WorkContinuation.enqueue()
method to enqueue() your chain of WorkContinuation
s.
Let's look at an example where an application runs image filters on 3 different images (potentially in parallel), then compresses those images together, and then uploads them.
WorkManager.getInstance()
// Candidates to run in parallel
.beginWith(Arrays.asList(filter1, filter2, filter3))
// Dependent work (only runs after all previous work in chain)
.then(compress)
.then(upload)
// Don't forget to enqueue()
.enqueue();
Input Mergers
When using chains of OneTimeWorkRequest
s, the output of parent OneTimeWorkRequest
s are passed in as inputs to the children. So in the above example, the outputs of filter1
, filter2
and filter3
would be passed in as inputs to the compress
request.
In order to manage inputs from multiple parent OneTimeWorkRequest
s, WorkManager uses InputMerger
s.
There are two different types of InputMerger
s provided by WorkManager:
OverwritingInputMerger
attempts to add all keys from all inputs to the output. In case of conflicts, it overwrites the previously-set keys.
ArrayCreatingInputMerger
attempts to merge the inputs, creating arrays when necessary.
For the above example, given we want to preserve the outputs from all image filters, we should use an ArrayCreatingInputMerger
.
OneTimeWorkRequest compress =
new OneTimeWorkRequest.Builder(CompressWorker.class)
.setInputMerger(ArrayCreatingInputMerger.class)
.setConstraints(constraints)
.build();
Chaining and Work Statuses
There are a couple of things to keep in mind when creating chains of OneTimeWorkRequest
s.
Dependent OneTimeWorkRequest
s are only unblocked (transition to ENQUEUED
), when all its parent OneTimeWorkRequest
s are successful (that is, they return a Result.success()
).
When any parent OneTimeWorkRequest
fails (returns a Result.failure()
, then all dependent OneTimeWorkRequest
s are also marked as FAILED
.
When any parent OneTimeWorkRequest
is cancelled, all dependent OneTimeWorkRequest
s are also marked as CANCELLED
.
For more information, see Cancelling and Stopping Work.
------------------------------------------------------------------
这一片简单总结一下,四个字:“链式调用”