如何使用WorkManager执行后台任务(下)
0x00 WorkManager的高级用法
在上一文中已经了解到 WorkManager的基本用法之后,今天来看看它的一些高级用法:
- 链式任务调用
- 唯一任务序列
- 传递参数和获取返回值
0x01 链式任务(Chained tasks)
WorkManager在执行多个工作任务的时候,可以指定执行顺序。假设一个应用程序中有3个 OneTimeWorkRequest对象: workA、 workB、 workC。这几个任务需要按照顺序执行,那么可以使用 WorkManager.beginWith()方法加入 workA,这时候会返回一个 WorkContinuation对象,它定义了工作任务的执行序列。然后通过它再调用 WorkContinuation.then()把 workB和 workC加入到执行队列中,最后执行 WorkManager.enqueue()方法。
WorkManager.getInstance()
.beginWith(workA)
// Note: WorkManager.beginWith() returns a
// WorkContinuation object; the following calls are
// to WorkContinuation methods
.then(workB) // FYI, then() returns a new WorkContinuation instance
.then(workC)
.enqueue()
WorkManager会按照指定的顺序来执行 workA、 workB、 workC。如果其中有一个工作任务执行的时候返回 Worker.Result.FAILURE,那么整个执行序列就会停止。
WorkManager.beginWith()方法可以传递多个 Worker对象,表示可以并行执行的任务组,然后再调用 then()方法。当这并行任务组都执行完之后才会执行接下来 then中的工作任务。
WorkManager.getInstance()
// 首先,并行执行workA1,workA2,workA3这三个任务
.beginWith(workA1, workA2, workA3)
// 当三个任务都完成之后, 开始执行workB:
.then(workB)
// 最后再并行执行 workC1,workC2
.then(workC1, workC2)
.enqueue()
还可以通过 WorkContinuation.combine()方法创建更加复杂的链接任务调用序列。它可以将两个 WorkContinuation对象合并,假设要调用如下的任务序列:

val chain1 = WorkManager.getInstance()
.beginWith(workA)
.then(workB)
val chain2 = WorkManager.getInstance()
.beginWith(workC)
.then(workD)
val chain3 = WorkContinuation
.combine(chain1, chain2)
.then(workE)
chain3.enqueue()
这个链式执行顺序是:子链 A->B 与子链 C->D 并行执行的, workA执行后再执行 workB,以及 workC执行后执行 workD ;然后等待 workB以及 workD都执行完,最后执行 workE。
需要注意的是, WorkManager无法保证两个子链的执行顺序,有可能 chain1比 chain2快,也有可能是 chain1比 chain2慢。
0x02 唯一任务序列(Unique work sequences)
在应用程序开发中,可能会多次把同一个链式任务添加到 WorkManager中,但希望只有一个链式任务在执行,这时候可以使用唯一任务序列对链式任务指定处理规则。假设,做一个下载文件操作,对一个文件下载链接,我们不需要重复下载,只需要添加一次,后面再添加这个任务,就忽略掉,因为我们不希望重复多次下载同一个文件。所以当添加两个同样名称为"download"操作任务时,对于唯一任务序列来说,可以通过 ExistingWorkPolicy中的 REPLACE, KEEP 和 APPEND,来指定添加的策略。
- REPLACE:新任务将替换旧的
- KEEP:新任务会被丢弃,旧的任务会被保持
- APPEND:追加,旧任务执行之后再执行新的任务。
使用 beginUniqueWork()方法可以创建任务序列,并且可以指定唯一的一个名称(name)。然后再 ExistingWorkPolicy指定任务的替换策略
WorkContinuation continuation = mWorkManager
.beginUniqueWork("download",
ExistingWorkPolicy.KEEP,
OneTimeWorkRequest.from(CleanupWorker))
0x03 传递参数和获取返回值
任务执行可以传递参数以及获取到任务执行的结果。使用 WorkRequst.Builder.setInputData()方法传递一个 Data对象,它是key-value形式的对象,使用 Data.Builder来创建。在 Worker类中可以使用 Worker.getInputData()获取到参数。
同样地,在 Worker中可以使用 Worker.setOutputData()设置一个 Data对象的返回值。要获取到这个返回值就通过 LiveData<WorkStatus>。
举个栗子:
有一个下载任务,在 Worker中获取传递过来的参数url,然后执行下载,最后设置下载结果。
// the result key:
const val KEY_RESULT = "result"
class DownloadWorker(context : Context, params : WorkerParameters) : Worker(context, params) {
override fun doWork(): Result {
// 获取参数
val url = getInputData("url")
// 执行下载
val result = download(url);
// 设置下载结果
val output: Data = mapOf(KEY_RESULT to result).toWorkData()
setOutputData(output)
// 任务执行成功
return Result.SUCCESS
}
}
然后,通过 WorkRequest传递参数
// 构造下载链接参数
val urlData: Data = mapOf("url" to "https://developer.android.com/images/topic/libraries/architecture/workmanager-chain.svg")
.toWorkData()
// 构造WorkRequest并传递下载参数
val downloadWork = OneTimeWorkRequest.Builder<DownloadWorker>()
.setInputData(urlData)
.build()
// 交给WorkManager执行任务
WorkManager.getInstance().enqueue(downloadWork)
最后,通过 WorkStatus获取返回值
WorkManager.getInstance().getStatusById(downloadWork.id)
.observe(this, Observer { status ->
if (status != null && status.state.isFinished) {
val myResult = status.outputData.getString(KEY_RESULT,
myDefaultValue)
// ... do something with the result ...
}
})
0x04 引用
https://developer.android.com/topic/libraries/architecture/workmanager/advanced
https://developer.android.com/reference/androidx/work/ExistingWorkPolicy
http://clmirror.storage.googleapis.com/codelabs/android-workmanager/index.html?index=..%2F..%2Findex#0
如何使用WorkManager执行后台任务(下)的更多相关文章
- 如何使用WorkManager执行后台任务(上)
0x00 简述 WorkManager 是 Android Jetpack中的一部分,它主要是封装了 Android 后台任务的调度逻辑.在前文<Android后台任务处理指南>一文中知道 ...
- 执行后台任务的利器——Hangfire
今年1月31日,在微软的MVP 2015社区大讲堂上,我给大家分享了一个演讲:在ASP.NET应用中执行后台任务.其中介绍了三种技术的应用:QueueBackgroundWorkItem.Hangfi ...
- MVP 2015社区大讲堂之:在ASP.NET应用中执行后台任务
昨天下午,在微软的MVP 2015社区大讲堂上给大家分享了一个题目:在ASP.NET应用中执行后台任务.这是一点都不高大上,并且还有点土气的技术分享.不过我相信很多人都遇到过这样的问题. 虽然是一个很 ...
- 在ASP.NET应用中执行后台任务
在ASP.NET应用中执行后台任务 昨天下午,在微软的MVP 2015社区大讲堂上给大家分享了一个题目:在ASP.NET应用中执行后台任务.这是一点都不高大上,并且还有点土气的技术分享.不过我相信很多 ...
- AsyncTask onPreExecute方法用于在执行后台任务前做一些UI操作
1.实例化 TableListsTask task = new TableListsTask(ServerIP,"ALL", MenuActivity.this); //第三参 ...
- go语言执行windows下命令行的方法
转自:http://www.jb51.net/article/61727.htm 在golang里执行windows下的命令行,例如在golang里面调用 del d:\a.txt 命令 packag ...
- 【Win 10 应用开发】在App所在的进程中执行后台任务
在以往版本中,后台任务都是以独立的专用进程来运行,因此,定义后台任务代码的类型都要位于 Windows 运行时组件项目中. 不过,在14393中,SDK 作了相应的扩展,不仅支持以前的独立进程中运行后 ...
- 执行后台任务的利器——Hangfire
Hangfire是一个开源且商业免费使用的工具函数库.可以让你非常容易地在ASP.NET应用(也可以不在ASP.NET应用)中执行多种类型的后台任务,而无需自行定制开发和管理基于Windows Ser ...
- jenkins不能执行windows下的命令,cmd可执行。
1.TortoiseSVN程序在安装时候,选择在windows下的命令行执行,要安装 2.安装后,“C:\Program Files\TortoiseSVN\bin”路径下就存在了命令行的一些指令 3 ...
随机推荐
- FC游戏修改教程(hack)小白文。
FC(NES)红白机Family Computer(简称FAMICOM)(或Nintendo Entertainment System)是任天堂公司发行的第一代家用游戏机. 修改FC游戏需要的工具有 ...
- weblogic10.3.6重置/修改控制台账号密码
weblogic部署服务后由于交接过程中文档不完整导致有一个域的控制台账号密码遗失, 在此整理记录一下重置控制台账号密码的过程: 注:%DOMAIN_HOME%:指WebLogic Server 域( ...
- 洛谷P2001 硬币的面值 题解
题目链接:https://www.luogu.org/problemnew/show/P2001 这题的数据范围吓得我很慌. 分析: 这道题蒟蒻本来想用背包的,但是发现m太大,一写肯定炸,然后看到数据 ...
- Java 8 终于支持 Docker!
Java 8曾经与Docker无法很好地兼容性,现在问题已消失. 请注意:我在本文中使用采用GNU GPL v2许可证的OpenJDK官方docker映像.在Oracle Java SE中,这里描述的 ...
- python面向过程编程小程序- 模拟超市收银系统
6.16自我总结 功能介绍 程序功能介绍: 商品信息再读取修改买卖均已xlsx格式 且生成购物记录也按/用户名/购买时间.xlsx格式生成 账号密码输入错误三次按照时间进行冻结 用户信息已json格式 ...
- 【MySQL】(三)文件
本篇文章分析构成MySQL数据库和InnoDB存储引擎表的各种累类型文件.这些文件有以下这些. 参数文件:告诉MySQL实例启动时在哪里可以找到数据库文件,并且指定某些初始化参数,这些参数定义了某种内 ...
- php上传excle文件,csv文件解析为二维数组
解析上传的CSV文件不是什么难事,直接读取转成你想要的数组样子就OK了. public function putStoreStockIn ($filePath = '') { $file = fope ...
- 用python输出回文数
一个b站上的朋友问我,怎么返回五位数的回文数的个数. 我首先百度回文数的概念,就是正读和倒读都一样的数字,例如:10001,99899 等等 数字的位数拆分一头雾水,思来想去,用字符串的方法完美解决! ...
- web设计_6_图片/标题/说明文字布局
这个web中常见的单元布局,最好的布局方式就是利用float布局. 其中有个很关键的问题是需要清浮动.子集浮动是无法撑开父级的高度. 目前较完善的清浮动解决方案:在浮动的父级上添加.clear,达到清 ...
- 基于redis的消息订阅与发布
Redis 的 SUBSCRIBE 命令可以让客户端订阅任意数量的频道, 每当有新信息发送到被订阅的频道时, 信息就会被发送给所有订阅指定频道的客户端. 作为例子, 下图展示了频道 channel1 ...