基础介绍

workmanager是一个可延期的后台异步任务,可以用来取代以前的android后台调度任务

通俗的讲就是可以用来做后台异步任务,那他有什么优势呢,和以前的后台api方法相比有什么区别呢?

带着这俩个问题开始往下看

兼容性

首先workmanager兼容性很好,包括 FirebaseJobDispatcher、GcmNetworkManager 和 JobScheduler

都可以替换成workmanager,同时支持 API 级别 14,对电量续航也做了优化(省电)

基础功能

创建方式:通过单例创建workmanager,enqueue方法将任务加入队列

val myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest)

任务(workrequest)是抽象基类,有俩个子类

OneTimeWorkRequest和PeriodicWorkRequest

OneTimeWorkRequest 适用于调度非重复性工作,而 PeriodicWorkRequest 则更适合调度以一定间隔重复执行的工作。

一次性工作:

val myWorkRequest = OneTimeWorkRequest.from(MyWork::class.java)

如果是复杂一点的一次性工作可以用构建器,可以在这里对你的任务添加一些策略

val uploadWorkRequest: WorkRequest =OneTimeWorkRequestBuilder<MyWork>()// Additional configuration.build()

定期性工作

val saveRequest =PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS)// Additional configuration.build()
//工作的运行时间间隔定为一小时。
//可以定义的最短重复间隔是 15 分钟

request由work类组成。work类就是具体执行流程的类

如下TestWork类继承Workr类,实现doWork方法,在里面上传图片

class TestWorker(appContext: Context, workerParams: WorkerParameters):Worker(appContext, workerParams) {override fun doWork(): Result {// Do the work here--in this case, upload the images.uploadImages()// Indicate whether the work finished successfully with the Resultreturn Result.success()}
}
从 doWork() 返回的 Result 会通知 WorkManager 服务工作是否成功,以及工作失败时是否应重试工作。
Result.success():工作成功完成。
Result.failure():工作失败。
Result.retry():工作失败,应根据其重试政策在其他时间尝试。

到这里,一个简单的workmanager就介绍完了,包括workmanager的创建方式,request的组成,work的创建

接下来是workmanger的一些配置

约束

可以给任务添加约束(比如在wifi条件下才运行,在充电状态下才运行)

val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.UNMETERED).setRequiresCharging(true).build()val myWorkRequest: WorkRequest =OneTimeWorkRequestBuilder<MyWork>().setConstraints(constraints).build()
//可以添加的约束类型如下

延迟工作

下面的示例为延迟10分钟

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>().setInitialDelay(10, TimeUnit.MINUTES).build()

调度

对于一组完整的异步任务,可以运行一次,也可以重复运行,对每一组任务进行命名,用来单独操作他们

//给一个单独的work添加标识
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>().addTag("cleanup").build()
//可以通过WorkManager.cancelAllWorkByTag(String)取消任务
//可以通过WorkManager.getWorkInfosByTag(String)获取这个任务,得到一个WorkInfo对象
//可以通过workManager.getWorkInfosByTagLiveData(String)得到一个livedata,当这个对象的tag的work执行完成之后,这个livedata会触发

灵活的重试机制

LINEAR和EXPONENTIAL俩种策略

当你在work的dowork方法中返回Result.retry()的时候,会进行重试机制

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>().setBackoffCriteria(BackoffPolicy.LINEAR,OneTimeWorkRequest.MIN_BACKOFF_MILLIS,TimeUnit.MILLISECONDS).build()
//MIN_BACKOFF_MILLIS为10秒
//LINEAR策略,每次尝试重试的时候,重试间隔都会增加10秒,20,30,40类推
//如果是EXPONENTIAL策略,那么重试时长是20、40、80 秒,以此类推。

work中的数据传递

// Define the Worker requiring input
class UploadWork(appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) {override fun doWork(): Result {val imageUriInput =inputData.getString("IMAGE_URI") ?: return Result.failure()uploadFile(imageUriInput)return Result.success()}...
}// Create a WorkRequest for your Worker and sending it input
val myUploadWork = OneTimeWorkRequestBuilder<UploadWork>().setInputData(workDataOf("IMAGE_URI" to "http://...")).build()//还可以通过 Result.success(outputData)将数据传递给下一个work

工作状态

一次性工作状态

对于 one-time 工作请求,工作的初始状态为 ENQUEUED

ENQUEUED 状态下,您的工作会在满足其 Constraints 和初始延迟计时要求后立即运行。接下来,该工作会转为 RUNNING 状态,然后可能会根据工作的结果转为 SUCCEEDEDFAILED 状态;或者,如果结果是 retry,它可能会回到 ENQUEUED 状态。在此过程中,随时都可以取消工作,取消后工作将进入 CANCELLED 状态。

SUCCEEDEDFAILEDCANCELLED 均表示此工作的终止状态。如果您的工作处于上述任何状态,WorkInfo.State.isFinished() 都将返回 true。

定期工作的状态

成功和失败状态仅适用于一次性工作和链式工作。定期工作只有一个终止状态 CANCELLED。这是因为定期工作永远不会结束。每次运行后,无论结果如何,系统都会重新对其进行调度。图 2 描述了定期工作的精简状态图。

唯一工作

确保在某一个时刻只有一个相同的实例存在

  • [WorkManager.enqueueUniqueWork()](https://developer.android.google.cn/reference/androidx/work/WorkManager#enqueueUniqueWork(java.lang.String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest))(用于一次性工作)
  • [WorkManager.enqueueUniquePeriodicWork()](https://developer.android.google.cn/reference/androidx/work/WorkManager#enqueueUniquePeriodicWork(java.lang.String, androidx.work.ExistingPeriodicWorkPolicy, androidx.work.PeriodicWorkRequest))(用于定期工作)

这两种方法都接受 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
)

上述代码在 sendLogs 作业已处于队列中的情况下运行,系统会保留现有的作业,并且不会添加新的作业

ExistingPeriodicWorkPolicy有三种选项

  • REPLACE:用新工作替换现有工作。此选项将取消现有工作。

  • KEEP:保留现有工作,并忽略新工作。

  • APPEND:将新工作附加到现有工作的末尾。此政策将导致您的新工作链接到现有工作,在现有工作完成后运行。

  • APPEND_OR_REPLACE 功能类似于 APPEND,不过它并不依赖于先决条件工作状态。即使现有工作变为 CANCELLEDFAILED 状态,新工作仍会运行。

状态监听

可以通过三种方式获取查询work

// by id
workManager.getWorkInfoById(syncWorker.id) // ListenableFuture<WorkInfo>// by name
workManager.getWorkInfosForUniqueWork("sync") // ListenableFuture<List<WorkInfo>>// by tag
workManager.getWorkInfosByTag("syncTag") // ListenableFuture<List<WorkInfo>>

该查询会返回 WorkInfo 对象的 ListenableFuture,该值包含工作的 id、其标记、其当前的 State 以及通过 Result.success(outputData) 设置的任何输出数据

下面的代码展示了,当syncWorker完成后,显示一个消息

workManager.getWorkInfoByIdLiveData(syncWorker.id).observe(viewLifecycleOwner) { workInfo ->if(workInfo?.state == WorkInfo.State.SUCCEEDED) {Snackbar.make(requireView(),R.string.work_completed, Snackbar.LENGTH_SHORT).show()}
}

复杂的work状态查询

以下示例说明了如何查找带有“syncTag”标记、处于 FAILEDCANCELLED 状态,且唯一工作名称为“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")

观察进度

在work的dowork方法中通过

setProgress(firstUpdate)//设置进度

观察进度

WorkManager.getInstance(applicationContext)// requestId is the WorkRequest id.getWorkInfoByIdLiveData(requestId).observe(observer, Observer { workInfo: WorkInfo? ->if (workInfo != null) {val progress = workInfo.progressval value = progress.getInt(Progress, 0)// Do something with progress information}})

链接工作

您可以使用 WorkManager 创建工作链并将其加入队列。工作链用于指定多个依存任务并定义这些任务的运行顺序。当您需要以特定顺序运行多个任务时,此功能尤其有用。

如需创建工作链,您可以使用 WorkManager.beginWith(OneTimeWorkRequest)WorkManager.beginWith(List),这会返回 WorkContinuation 实例。

然后,可以使用 WorkContinuation 通过 then(OneTimeWorkRequest)then(List) 添加依存 OneTimeWorkRequest。 .

每次调用 WorkContinuation.then(...) 都会返回一个新的 WorkContinuation 实例。如果添加了 OneTimeWorkRequest 实例的 List,这些请求可能会并行运行。

最后,您可以使用 WorkContinuation.enqueue() 方法对 WorkContinuation 工作链执行 enqueue() 操作。

下面我们来看一个示例。在本例中,有 3 个不同的工作器作业配置为运行(可能并行运行)。然后这些工作器的结果将联接起来,并传递给正在缓存的工作器作业。最后,该作业的输出将传递到上传工作器,由上传工作器将结果上传到远程服务器。

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()

如果想将plantName1, plantName2, plantName3work的输出作为下一个work cache的输入。那么就需要用到输入合并器

WorkManager 提供两种不同类型的 InputMerger

  • OverwritingInputMerger 会尝试将所有输入中的所有键添加到输出中。如果发生冲突,它会覆盖先前设置的键。
  • ArrayCreatingInputMerger 会尝试合并输入,并在必要时创建数组。

也可以创建 InputMerger 的子类来编写自己的用例。

by the last最后说一下

请注意,Worker.doWork() 是同步调用 - 您将会以阻塞方式完成整个后台工作,并在方法退出时完成工作。如果您在 doWork() 中调用异步 API 并返回 Result,则回调可能无法正常运行。如果您遇到这种情况,请考虑使用 ListenableWorker(请参阅在 ListenableWorker 中进行线程处理)。

jetpack之workManager官方文档解析相关推荐

  1. sanic官方文档解析之下载和Configuration

    1,sanic框架是做什么的? sanic的官方网址:https://sanic.readthedocs.io/en/latest/ sanic框架是一个类似于flask框架的在Python3.5以上 ...

  2. 【开源项目推荐】Android Jetpack 官方文档 中文翻译

    Jetpack 是 Android 软件组件的集合,使您可以更轻松地开发出色的 Android 应用.这些组件可帮助您遵循最佳做法.让您摆脱编写样板代码的工作并简化复杂任务,以便您将精力集中放在所需的 ...

  3. HarmonyOS(一) 快速开始学习鸿蒙开发,官方文档学习路线解析

    系列文章目录 HarmonyOS(一):快速开始学习鸿蒙开发,官方文档学习路线解析 HarmonyOS(二):应用开发环境搭建准备 HarmonyOS(三):创建你的第一个HelloWorld应用 文 ...

  4. excel函数从0到掌握(官方文档+自我解析)

    excel函数从0到掌握 我写到一半,发觉网上的资料还不如,wps自带的视频讲解,在这里提醒你们一下!(不是打广告,视频免费) 四大运算符 算术运算符 比较运算符 文本运算符 引用运算符 优先级 1. ...

  5. 解析:urllib.request(内附有官方文档)

    解析:urllib.request(内附有官方文档) urllib.request - Extensible library for opening URLs import urllib.reques ...

  6. Qt官方文档阅读笔记-对官方Star Delegate Example实例的解析

    对应的博文为: 目录 Star Delegate Example StarDelegate Class Definition StarDelegate Class Implementation Sta ...

  7. 深入理解Java 8 Lambda表达式(Oracle官方文档版)

    Java 8 问世三年了,9马上也要问世了,所以,嗯,我要开始学8了-- 官方文档:http://docs.oracle.com/javase/tutorial/java/javaOO/lambdae ...

  8. scrapy 中不同页面的拼接_scrapy官方文档提供的常见使用问题

    Scrapy与BeautifulSoup或lxml相比如何? BeautifulSoup和lxml是用于解析HTML和XML的库.Scrapy是一个用于编写Web爬虫的应用程序框架,可以抓取网站并从中 ...

  9. Spring 4 官方文档学习(十一)Web MVC 框架之异常处理

    1.HandlerExceptionResolver Spring HandlerExceptionResolver的实现们会处理controller执行过程中发送的unexpected except ...

  10. OpenTsdb官方文档-----理解指标和时间序列

      OpenTSDB是一个时间序列数据库.时间序列是一段时间内某个特定指标量的一系列数值数据点.每个时间序列由一个指标量加上一个或多个与此指标量相关联的标签组成(我们会稍微介绍一下标签).指标量是您希 ...

最新文章

  1. 实战:使用 OpenCV 的自动驾驶汽车车道检测(附代码)
  2. 重大疫情给企业管理带来的挑战,企业的管理应如何应对?
  3. 全球首个AI女主播上岗了!太惊艳了!
  4. wParam和lParam两个参数到底是什么意思?
  5. 一加6升级android p,一加6手机升级安卓P攻略 教你怎么更新安卓P Beta版
  6. 网络管理技术(Network Administrative Techniques)
  7. pytorch 实现openpose
  8. Android WebView 支持H5的定位Js
  9. UA OPTI512R 傅立叶光学导论11 卷积的性质
  10. 理解Node.js(译文)
  11. WPF效果第一百七十八篇ItemsControl旋转
  12. 【数据库系统】笛卡尔积与自然连接
  13. Python中的字符串比较:与== [重复]
  14. php mysql 命令行模式_phpstudy(mysql命令行的增删改查)
  15. HBase二级索引的设计原理及简单设计demo
  16. 个人博客前后台整站开发——模板免费下载
  17. 孪生支持向量机基本原理
  18. 钉钉微应用调用支付宝JSAPI进行支付
  19. 强化学习-利用Q-Learning算法玩走方格游戏(C++)
  20. Qt的对话框与窗口--Qt中主要的窗体类及其用途

热门文章

  1. Linux中tar分卷压缩与解压缩
  2. 分布式任务调度:你知道和不知道的事
  3. vue element-ui实现input输入框金额数字添加千分位
  4. 一级计算机网络应用题目操作,计算机一级考试excel操作题目
  5. java.io的缓冲流、转换流、序列化流
  6. remoting 最简单的一个例子
  7. 15本职场必读书,得挑几本看看!
  8. 如何批量保存虾皮购物中的商品主图、颜色分类图片
  9. h2o java_java – 在h2o中加载大于内存大小的数据
  10. Android 调用第三方地图类App (高德 百度 百度网页版)