工作链

WorkManager 允许您创建和排队一系列工作,该工作指定多个依赖任务并定义其运行顺序。当您需要按特定顺序运行多个任务时,此功能特别有用。

要创建一系列工作,您可以使用 WorkManager.beginWith(OneTimeWorkRequest)WorkManager.beginWith(List<OneTimeWorkRequest>),它们都返回 WorkContinuation 的实例。

WorkContinuation 然后可用于使用 then(OneTimeWorkRequest)then(List<OneTimeWorkRequest>) 添加依赖的 OneTimeWorkRequest 实例。

每次调用 WorkContinuation.then(...) 都会返回 WorkContinuation实例。如果您添加 OneTimeWorkRequest 实例的 List,则这些请求可能会并行运行。

最后,您可以使用 WorkContinuation.enqueue() 方法来 enqueue() 您的一系列 WorkContinuation

让我们来看一个示例。在此示例中,配置了 3 个不同的 Worker 作业以运行(可能并行)。然后,这些 Worker 的结果将合并并传递给缓存 Worker 作业。最后,该作业的输出将传递到上传 Worker,后者将结果上传到远程服务器。

Kotlin

WorkManager.getInstance(myContext)
   // Candidates to run in parallel
   .beginWith(listOf(plantName1, plantName2, plantName3))
   // Dependent work (only runs after all previous work in chain)
   .then(cache)
   .then(upload)
   // Call enqueue to kick things off
   .enqueue()

Java

WorkManager.getInstance(myContext)
   // Candidates to run in parallel
   .beginWith(Arrays.asList(plantName1, plantName2, plantName3))
   // Dependent work (only runs after all previous work in chain)
   .then(cache)
   .then(upload)
   // Call enqueue to kick things off
   .enqueue();

输入合并器

当您链接 OneTimeWorkRequest 实例时,父工作请求的输出将作为输入传递给子级。因此,在上面的示例中,plantName1plantName2plantName3 的输出将作为输入传递给 cache 请求。

为了管理来自多个父工作请求的输入,WorkManager 使用 InputMerger

WorkManager 提供了两种不同类型的 InputMerger

如果您有更具体的用例,则可以通过子类化 InputMerger 来编写自己的合并器。

OverwritingInputMerger

OverwritingInputMerger 是默认的合并方法。如果合并器中存在键冲突,则键的最新值将覆盖结果输出数据中的任何先前版本。

例如,如果每个工厂输入都具有与其各自变量名称匹配的键("plantName1""plantName2""plantName3"),则传递到 cache 工作器的的数据将包含三个键值对。

Diagram showing three jobs passing different outputs to the next job in the chain. Since the three outputs all have different keys, the next job receives three key/value pairs.

如果存在冲突,则最后一个完成“获胜”的工作器的值将传递给 cache

Diagram showing three jobs passing outputs to the next job in the chain. In this case, two of those jobs produce outputs with the same key. As a result, the next job receives two key/value pairs, with one of the conflicting outputs dropped.

由于您的工作请求是并行运行的,因此您无法保证其运行顺序。在上面的示例中,plantName1 可以保存 "tulip""elm" 的值,具体取决于最后写入的值。如果您存在键冲突的可能性,并且需要在合并器中保留所有输出数据,则 ArrayCreatingInputMerger 可能是一个更好的选择。

ArrayCreatingInputMerger

对于上述示例,鉴于我们希望保留所有工厂名称工作器的输出,我们应该使用 ArrayCreatingInputMerger

Kotlin

val cache: OneTimeWorkRequest = OneTimeWorkRequestBuilder<PlantWorker>()
   .setInputMerger(ArrayCreatingInputMerger::class)
   .setConstraints(constraints)
   .build()

Java

OneTimeWorkRequest cache = new OneTimeWorkRequest.Builder(PlantWorker.class)
       .setInputMerger(ArrayCreatingInputMerger.class)
       .setConstraints(constraints)
       .build();

ArrayCreatingInputMerger 将每个键与一个数组配对。如果每个键都是唯一的,则您的结果是一系列单元素数组。

Diagram showing three jobs passing different outputs to the next job in the chain. The next job is passed three arrays, one for each of the output keys. Each array has a single member.

如果存在任何键冲突,则任何相应的 value 将组合在一起形成一个数组。

Diagram showing three jobs passing outputs to the next job in the chain. In this case, two of those jobs produce outputs with the same key. The next job is passed two arrays, one for each key. One of those arrays has two members, since there were two outputs with that key.

链和工作状态

只要其工作成功完成(即返回 Result.success()),OneTimeWorkRequest 的链就会依次执行。工作请求在运行时可能会失败或被取消,这会对下游的依赖工作请求产生影响。

当第一个 OneTimeWorkRequest 在工作请求链中入队时,所有后续工作请求都将被阻塞,直到第一个工作请求的工作完成。

Diagram showing a chain of jobs. The first job is enqueued; all successive jobs are blocked until the first one finishes.

一旦入队并且所有工作约束都得到满足,第一个工作请求就开始运行。如果根 OneTimeWorkRequestList<OneTimeWorkRequest> 中的工作成功完成(即返回 Result.success()),则下一组依赖工作请求将被入队。

Diagram showing a chain of jobs. The first job has succeeded, and its two immediate successors are enqueued. The remaining jobs are blocked their preceding jobs finish.

只要每个工作请求都成功完成,这种模式就会传播到工作请求链的其余部分,直到链中的所有工作都完成。虽然这是最简单且通常是首选的情况,但错误状态同样重要。

当工作器在处理您的工作请求时发生错误时,您可以根据 您定义的回退策略 重试该请求。重试链中的一部分请求意味着仅重试该请求以及提供给它的输入数据。任何并行运行的工作都不会受到影响。

Diagram showing a chain of jobs. One of the jobs failed, but had a backoff policy defined. That job will rerun after the appropriate amount of time has passed. The jobs after it in the chain are blocked until it runs successfully.

有关定义自定义重试策略的更多信息,请参阅 重试和回退策略

如果该重试策略未定义或已用尽,或者您以其他方式达到 OneTimeWorkRequest 返回 Result.failure() 的某种状态,则该工作请求和所有依赖工作请求都将标记为 FAILED。

Diagram showing a chain of jobs. One job has failed and cannot be retried. As a result, all jobs after it in the chain also fail.

OneTimeWorkRequest 被取消时,也会应用相同的逻辑。所有依赖工作请求也标记为 CANCELLED,并且不会执行其工作。

Diagram showing a chain of jobs. One job has been cancelled. As a result, all jobs after it in the chain are also cancelled.

请注意,如果您要向已失败或已取消工作请求的链中追加更多工作请求,则新追加的工作请求也将分别标记为 FAILEDCANCELLED。如果您想扩展现有链的工作,请参阅 ExistingWorkPolicy 中的 APPEND_OR_REPLACE

在创建工作请求链时,依赖工作请求应定义重试策略,以确保工作始终及时完成。失败的工作请求可能导致链不完整和/或出现意外状态。

有关更多信息,请参阅 取消和停止工作