当前位置:网站首页>WorkManager的学习二
WorkManager的学习二
2022-07-05 09:49:00 【Mr_Tony】
一、前言
Work在运行期间有几种状态。在运行过程中, State也随之改变。当任务开始是,状态是 ENQUEUED。运行时转变为RUNNING,运行结束时会变成 SUCCEEDED、FAILED。如果是重试的话,状态会重新回到ENQUEUED。如果取消工作,状态就会变成 CANCELLED。
SUCCEEDED、FAILED 和 CANCELLED 均表示此工作的终止状态。如果您的工作处于上述任何状态,WorkInfo.State.isFinished() 都将返回 true。
以下是任务执行的流程图

上面是一个一次性任务的执行流程。如果是定时任务,那么就不会有SUCCEEDED、FAILED状态。以下是定时任务的流程图。

二、唯一工作
一般来说启动工作可以使用以下方式
WorkManager
.getInstance(this)
.enqueue(uploadWorkRequest)
不过如果我们无意中写了两次该代码,那么任务就会执行两次(虽说这个是不应该出现的)。为了避免这个问题,官方对一次性任务和定时任务分别提供了保证其唯一执行的方式。
这两种方法都接受 3 个参数:
- uniqueWorkName - 用于唯一标识工作请求的
String。 - existingWorkPolicy - 此
enum可告知 WorkManager:如果已有使用该名称且尚未完成的唯一工作链,应执行什么操作。如需了解详情,请参阅冲突解决政策。 - work - 要调度的
WorkRequest。
参考代码如下:
val sendLogsWorkRequest =
PeriodicWorkRequestBuilder<SendLogsWorker>(24, TimeUnit.HOURS)
.setConstraints(Constraints.Builder()
.setRequiresCharging(true)
.build()
)
.build()
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
"sendLogs",
ExistingPeriodicWorkPolicy.KEEP,
sendLogsWorkRequest
)
三、冲突策略
以下参考官网
调度唯一工作时,您必须告知 WorkManager 在发生冲突时要执行的操作。您可以通过在将工作加入队列时传递一个枚举来实现此目的。
对于一次性工作,您需要提供一个
ExistingWorkPolicy,它支持用于处理冲突的 4 个选项。
REPLACE:用新工作替换现有工作。此选项将取消现有工作。KEEP:保留现有工作,并忽略新工作。APPEND:将新工作附加到现有工作的末尾。此政策将导致您的新工作链接到现有工作,在现有工作完成后运行。现有工作将成为新工作的先决条件。如果现有工作变为
CANCELLED或FAILED状态,新工作也会变为CANCELLED或FAILED。如果您希望无论现有工作的状态如何都运行新工作,请改用APPEND_OR_REPLACE。
APPEND_OR_REPLACE函数类似于APPEND,不过它并不依赖于先决条件工作状态。即使现有工作变为CANCELLED或FAILED状态,新工作仍会运行。对于定期工作,您需要提供一个
ExistingPeriodicWorkPolicy,它支持REPLACE和KEEP这两个选项。这些选项的功能与其对应的 ExistingWorkPolicy 功能相同。
四、观察工作的状态
当工作启动后,可以通过以下方式获取相应的工作信息。
// by id
workManager.getWorkInfoById(syncWorker.id) // ListenableFuture<WorkInfo>
// by name
workManager.getWorkInfosForUniqueWork("sync") // ListenableFuture<List<WorkInfo>>
// by tag
workManager.getWorkInfosByTag("syncTag") // ListenableFuture<List<WorkInfo>>
上面三种获取的方式对应的赋值方式如下:
// by id
val uploadWorkRequest: OneTimeWorkRequest = OneTimeWorkRequest.from(WorkTest::class.java)//简单方式
val workerId = uploadWorkRequest.id
//by name
WorkManager
.getInstance(this)
.enqueueUniqueWork("workName",
ExistingWorkPolicy.KEEP,
uploadWorkRequest)
//by tag
val uploadWorkRequest: WorkRequest = //复杂的构建器方式
OneTimeWorkRequestBuilder<WorkTest>()
.addTag("first")
.build()
该查询会返回
WorkInfo对象的ListenableFuture,该值包含工作的id、其标记、其当前的State以及通过Result.success(outputData)设置的任何输出数据。利用每个方法的
LiveData变种,您可以通过注册监听器来观察WorkInfo的变化(需要注意的是调用的函数名字是getWorkInfoByIdLiveData而不是getWorkInfoById())。例如,如果您想要在某项工作成功完成后向用户显示消息,您可以进行如下设置:workManager.getWorkInfoByIdLiveData(syncWorker.id) .observe(viewLifecycleOwner) { workInfo -> if(workInfo?.state == WorkInfo.State.SUCCEEDED) { Snackbar.make(requireView(), R.string.work_completed, Snackbar.LENGTH_SHORT) .show() } }
五、复杂的查询
WorkManager 2.4.0 及更高版本支持使用
WorkQuery对象对已加入队列的作业进行复杂查询。WorkQuery 支持按工作的标记、状态和唯一工作名称的组合进行查询。以下示例说明了如何查找带有“syncTag”标记、处于
FAILED或CANCELLED状态,且唯一工作名称为“preProcess”或“sync”的所有工作。val workQuery = WorkQuery.Builder .fromTags(listOf("syncTag")) .addStates(listOf(WorkInfo.State.FAILED, WorkInfo.State.CANCELLED)) .addUniqueWorkNames(listOf("preProcess", "sync")) .build() val workInfos: ListenableFuture<List<WorkInfo>> = workManager.getWorkInfos(workQuery)
WorkQuery中的每个组件(标记、状态或名称)与其他组件都是AND逻辑关系。组件中的每个值都是OR逻辑关系。例如:(name1 OR name2 OR ...) AND (tag1 OR tag2 OR ...) AND (state1 OR state2 OR ...)。
WorkQuery也适用于等效的 LiveData 方法getWorkInfosLiveData()。
六、取消和停止工作
任务有时候需要取消,可以使用以下方式
// by id
workManager.cancelWorkById(syncWorker.id)
// by name
workManager.cancelUniqueWork("sync")
// by tag
workManager.cancelAllWorkByTag("syncTag")
WorkManager 会在后台检查工作的
State。如果工作已经完成,系统不会执行任何操作。否则,工作的状态会更改为CANCELLED,之后就不会运行这个工作。任何依赖于此工作的WorkRequest作业也将变为CANCELLED。目前,
RUNNING可收到对ListenableWorker.onStopped()的调用。如需执行任何清理操作,请替换此方法。如需了解详情,请参阅停止正在运行的工作器。
所以任务停止后,可以在重写的onStopped()函数中处理收尾工作。也可以通过 ListenableWorker.isStopped()来见擦汗任务是否停止,示例如下:
class WorkTest(val appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) {
override fun doWork(): Result {
if(isStopped){
return Result.success()
}
return Result.success()
}
}
七、参考链接
边栏推荐
猜你喜欢
![[system design] index monitoring and alarm system](/img/83/81534fa31b525c4c7b3175d8312808.png)
[system design] index monitoring and alarm system

《微信小程序-基础篇》小程序中的事件与冒泡

QT event filter simple case

Swift tableview style (I) system basic

【小技巧】获取matlab中cdfplot函数的x轴,y轴的数值

mysql80服务不启动

(1) Complete the new construction of station in Niagara vykon N4 supervisor 4.8 software

B站大量虚拟主播被集体强制退款:收入蒸发,还倒欠B站;乔布斯被追授美国总统自由勋章;Grafana 9 发布|极客头条...

自动化规范检查软件如何发展而来?

一种用于干式脑电图的高密度256通道电极帽
随机推荐
Cut off 20% of Imagenet data volume, and the performance of the model will not decline! Meta Stanford et al. Proposed a new method, using knowledge distillation to slim down the data set
ConstraintLayout的流式布局Flow
天龙八部TLBB系列 - 单体技能群伤
历史上的今天:第一本电子书问世;磁条卡的发明者出生;掌上电脑先驱诞生...
橫向滾動的RecycleView一屏顯示五個半,低於五個平均分布
Node red series (29): use slider and chart nodes to realize double broken line time series diagram
[NTIRE 2022]Residual Local Feature Network for Efficient Super-Resolution
pytorch输出tensor张量时有省略号的解决方案(将tensor完整输出)
Flutter development: a way to solve the problem of blank space on the top of listview
isEmpty 和 isBlank 的用法区别
微信小程序中,从一个页面跳转到另一个页面后,在返回后发现页面同步滚动了
C#函数返回多个值方法
Kotlin compose multiple item scrolling
程序员搞开源,读什么书最合适?
Livedata interview question bank and answers -- 7 consecutive questions in livedata interview~
Using directive in angualr2 to realize that the picture size changes with the window size
硬核,你见过机器人玩“密室逃脱”吗?(附代码)
Generics, generic defects and application scenarios that 90% of people don't understand
Matrix processing practice
Fluent development: setting method of left and right alignment of child controls in row