本篇记录下WorkManager的进度观察和多个Work链接的内容。
WorkManager提供对进度的观察,示例如下:
更新进度:
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.Data
import androidx.work.WorkerParameters
import kotlinx.coroutines.delay
class ProgressWorker(context: Context, parameters: WorkerParameters) :
CoroutineWorker(context, parameters) {
companion object {
const val Progress = "Progress"
private const val delayDuration = 1L
}
override suspend fun doWork(): Result {
val firstUpdate = workDataOf(Progress to 0)
val lastUpdate = workDataOf(Progress to 100)
setProgress(firstUpdate)
delay(delayDuration)
setProgress(lastUpdate)
return Result.success()
}
}
观察进度:
WorkManager.getInstance(applicationContext)
// requestId is the WorkRequest id
.getWorkInfoByIdLiveData(requestId)
.observe(observer, Observer { workInfo: WorkInfo? ->
if (workInfo != null) {
val progress = workInfo.progress
val value = progress.getInt(Progress, 0)
// Do something with progress information
}
})
需要注意的是,getWorkInfoById()在实际测试中无法监听进度,暂时原因未知。而且仅会在任务开始时候执行一次,其后就不再执行,所以倘若任务延迟后,那么可能获取不到实际的结果。
WorkManager在实际工作中允许将多个Work进行链接,进行并发或者顺序执行。
如需创建工作链,您可以使用
WorkManager.beginWith(OneTimeWorkRequest)或WorkManager.beginWith(List<OneTimeWorkRequest>),这会返回WorkContinuation实例。然后,可以使用
WorkContinuation通过then(OneTimeWorkRequest)或then(List<OneTimeWorkRequest>)添加OneTimeWorkRequest依赖实例。 .每次调用
WorkContinuation.then(...)都会返回一个新的WorkContinuation实例。如果添加了OneTimeWorkRequest实例的List,这些请求可能会并行运行。最后,您可以使用
WorkContinuation.enqueue()方法对WorkContinuation工作链执行enqueue()操作。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()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
在WorkManager的链式调用中,每一次的工作结果都会成为下一个工作的输入内容。为了管理这种事情,WorkManager使用 InputMerger来处理这种事情。
WorkManager 提供两种不同类型的
InputMerger:
OverwritingInputMerger会尝试将所有输入中的所有键添加到输出中。如果发生冲突,它会覆盖先前设置的键。
ArrayCreatingInputMerger会尝试合并输入,并在必要时创建数组。如果您有更具体的用例,则可以创建
InputMerger的子类来编写自己的用例
示例代码如下:
val cache: OneTimeWorkRequest = OneTimeWorkRequestBuilder<PlantWorker>()
.setInputMerger(ArrayCreatingInputMerger::class)
.setConstraints(constraints)
.build()