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
实例时,父工作请求的输出将作为输入传递给子级。因此,在上面的示例中,plantName1
、plantName2
和 plantName3
的输出将作为输入传递给 cache
请求。
为了管理来自多个父工作请求的输入,WorkManager 使用 InputMerger
。
WorkManager 提供了两种不同类型的 InputMerger
OverwritingInputMerger
尝试将所有输入中的所有键添加到输出中。如果发生冲突,它将覆盖先前设置的键。ArrayCreatingInputMerger
尝试合并输入,在必要时创建数组。
如果您有更具体的用例,则可以通过子类化 InputMerger
来编写自己的合并器。
OverwritingInputMerger
OverwritingInputMerger
是默认的合并方法。如果合并器中存在键冲突,则键的最新值将覆盖结果输出数据中的任何先前版本。
例如,如果每个工厂输入都具有与其各自变量名称匹配的键("plantName1"
、"plantName2"
和 "plantName3"
),则传递到 cache
工作器的的数据将包含三个键值对。
如果存在冲突,则最后一个完成“获胜”的工作器的值将传递给 cache
。
由于您的工作请求是并行运行的,因此您无法保证其运行顺序。在上面的示例中,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
将每个键与一个数组配对。如果每个键都是唯一的,则您的结果是一系列单元素数组。
如果存在任何键冲突,则任何相应的 value 将组合在一起形成一个数组。
链和工作状态
只要其工作成功完成(即返回 Result.success()
),OneTimeWorkRequest
的链就会依次执行。工作请求在运行时可能会失败或被取消,这会对下游的依赖工作请求产生影响。
当第一个 OneTimeWorkRequest
在工作请求链中入队时,所有后续工作请求都将被阻塞,直到第一个工作请求的工作完成。
一旦入队并且所有工作约束都得到满足,第一个工作请求就开始运行。如果根 OneTimeWorkRequest
或 List<OneTimeWorkRequest>
中的工作成功完成(即返回 Result.success()
),则下一组依赖工作请求将被入队。
只要每个工作请求都成功完成,这种模式就会传播到工作请求链的其余部分,直到链中的所有工作都完成。虽然这是最简单且通常是首选的情况,但错误状态同样重要。
当工作器在处理您的工作请求时发生错误时,您可以根据 您定义的回退策略 重试该请求。重试链中的一部分请求意味着仅重试该请求以及提供给它的输入数据。任何并行运行的工作都不会受到影响。
有关定义自定义重试策略的更多信息,请参阅 重试和回退策略。
如果该重试策略未定义或已用尽,或者您以其他方式达到 OneTimeWorkRequest
返回 Result.failure()
的某种状态,则该工作请求和所有依赖工作请求都将标记为 FAILED。
当 OneTimeWorkRequest
被取消时,也会应用相同的逻辑。所有依赖工作请求也标记为 CANCELLED
,并且不会执行其工作。
请注意,如果您要向已失败或已取消工作请求的链中追加更多工作请求,则新追加的工作请求也将分别标记为 FAILED
或 CANCELLED
。如果您想扩展现有链的工作,请参阅 ExistingWorkPolicy 中的 APPEND_OR_REPLACE
。
在创建工作请求链时,依赖工作请求应定义重试策略,以确保工作始终及时完成。失败的工作请求可能导致链不完整和/或出现意外状态。
有关更多信息,请参阅 取消和停止工作。