您可以使用 WorkManager 创建工作链并将其加入队列。工作链用于指定多个依存任务并定义这些任务的运行顺序。当您需要以特定顺序运行多个任务时,此功能尤其有用。
如需创建工作链,您可以使用 WorkManager.beginWith(OneTimeWorkRequest)
或 WorkManager.beginWith(List<OneTimeWorkRequest>)
,这会返回 WorkContinuation
实例。
然后,可以使用 WorkContinuation
通过 then(OneTimeWorkRequest)
或 then(List<OneTimeWorkRequest>)
添加 OneTimeWorkRequest
依赖实例。
.
每次调用 WorkContinuation.then(...)
都会返回一个新的 WorkContinuation
实例。如果添加了 OneTimeWorkRequest
实例的 List
,这些请求可能会并行运行。
最后,您可以使用 WorkContinuation.enqueue()
方法对 WorkContinuation
工作链执行 enqueue()
操作。
下面我们来看一个示例。在本例中,有 3 个不同的工作器作业配置为运行(可能并行运行)。然后这些工作器的结果将联接起来,并传递给正在缓存的工作器作业。最后,该作业的输出将传递到上传工作器,由上传工作器将结果上传到远程服务器。
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
将每个键与数组配对。如果每个键都是唯一的,您会得到一系列一元数组。
如果存在任何键冲突,那么所有对应的值会分组到一个数组中。
链接和工作状态
只要工作成功完成(即,返回 Result.success()
),OneTimeWorkRequest
链便会按顺序执行。运行时,工作请求可能会失败或被取消,这会对依存工作请求产生下游影响。
当第一个 OneTimeWorkRequest
被加入工作请求链队列时,所有后续工作请求会被屏蔽,直到第一个工作请求的工作完成为止。
在加入队列且满足所有工作约束后,第一个工作请求开始运行。如果工作在根 OneTimeWorkRequest
或 List<OneTimeWorkRequest>
中成功完成(即返回 Result.success()
),系统会将下一组依存工作请求加入队列。
只要每个工作请求都成功完成,工作请求链中的剩余工作请求就会遵循相同的运行模式,直到链中的所有工作都完成为止。这是最简单的用例,通常也是首选用例,但处理错误状态同样重要。
如果在工作器处理工作请求时出现错误,您可以根据您定义的退避政策来重试该请求。重试请求链中的某个请求意味着,系统将使用提供给该请求的输入数据仅对该请求进行重试。并行运行的所有其他作业均不会受到影响。
如需详细了解如何定义自定义重试策略,请参阅重试和退避政策。
如果该重试政策未定义或已用尽,或者您以其他方式已达到 OneTimeWorkRequest
返回 Result.failure()
的某种状态,该工作请求和所有依存工作请求都会被标记为 FAILED.
OneTimeWorkRequest
被取消时遵循相同的逻辑。任何依存工作请求也会被标记为 CANCELLED
,并且无法执行其工作。
请注意,如果要向已失败或已取消工作请求的链附加更多工作请求,新附加的工作请求也会分别标记为 FAILED
或 CANCELLED
。如果您想扩展现有链的工作,请参阅 ExistingWorkPolicy 中的 APPEND_OR_REPLACE
。
创建工作请求链时,依存工作请求应定义重试政策,以确保始终及时完成工作。失败的工作请求可能会导致链不完整和/或出现意外状态。
如需了解详情,请参阅取消和停止工作。