Jetpack系列之WorkManager 任务管理
创始人
2025-06-01 19:11:51
0

(一)概述

WorkManager 概述:WorkManager 可以自动维护后台链式任务的执行时机、执行状态。

WorkManager 一般用于多文件上传,复杂计算,多流程控制等。

// WorkManager
api 'androidx.work:work-runtime:2.2.0'

Data的优势: 1)一组持久的键(字符串)/ 值(字符串、基本元素或其数组变量)对,用作ListenableWorkers的输入和输出; 2)有效负载的串行化(字节数组)大小限制10KB; 3)支持序列化和反序列化持久操作,更轻量级(轻量级HashMap)。

WorkManager操作:

 // 同时执行A(先)->B(后)、C(先)->D(后), 最后执行E    WorkContinuation left = workManager.beginWith(A).then(B);WorkContinuation right = workManager.beginWith(C).then(D);WorkContinuation final = WorkContinuation.combine(Arrays.asList(left, right)).then(E);final.enqueue();

(二)示例代码

// step 1.创建 Worker
/*** 上传文件Worker (Worker一般用做文件上传,任务的计算等操作)** WorkManager在运行时实例化Worker类,并在预先指定的后台线程上调用doWork()方法,* 此doWork方法用于同步处理您的工作,这意味着一旦您从该方法返回,Worker将被视为已完成并将被销毁。* 如果工作因任何原因被抢占,则不会重用Worker的同一实例。这意味着每个Worker实例只调用一次doWork(),** 如果需要重新运行某个工作单元,将创建一个新的Worker。* 如果需要异步工作或调用异步API,则应使用ListenableWorker。** Worker 最多有十分钟的时间完成其执行并返回 ListenableWorker.Result。在此时间到期后,将向 Worker 发出停止的信号.*/
class UploadFileWorker(context: Context, workerParams: WorkerParameters) :Worker(context, workerParams) {// getBackgroundExecutor().execute 该方法在后台线程中执行override fun doWork(): Result {// 获取Data携带到数据val filePath = inputData.getString("file")// 真正执行任务val fileUrl = FileUploadManager.upload(filePath)return if (TextUtils.isEmpty(fileUrl)) {Result.failure()} else {// 将拿到的数据回传出去val outputData = Data.Builder().putString("fileUrl", fileUrl).build()Result.success(outputData)}}
}// step 2.创建 Data,作为worker的输入和输出
val inputData = Data.Builder().putString("file", filePath)// 这里只添加一个file参数.build()// step 3.创建 WorkRequest。一般有两种:
// PeriodicWorkRequest 多次、周期性任务请求,不支持任务链,
// OneTimeWorkRequest 只执行一次的任务请求,支持任务链。
// 注意:每个WorkRequest都有个id标识(uuid类型)唯一请求。
以OneTimeWorkRequest为例:val workRequest = OneTimeWorkRequest.Builder(UploadFileWorker::class.java)// 指定worker.setInputData(inputData)// 设置Data(作为入参)//.setXXX ,也可以设置一大堆.build()如:
//          .setConstraints(constraints)
//          // 设置一个拦截器,在任务执行之前 可以做一次拦截,
//          去修改入参的数据, 然后返回新的数据交由worker使用
//          .setInputMerger(null)
//          //当一个任务被调度失败后,所要采取的重试策略,可以通过BackoffPolicy来执行具体的策略
//         .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 10, TimeUnit.SECONDS)
//         //任务被调度执行的延迟时间
//          .setInitialDelay(10, TimeUnit.SECONDS)// 设置该任务尝试执行的最大次数
//          .setInitialRunAttemptCount(2)
//          //设置这个任务开始执行的时间
//          //System.currentTimeMillis()
//          .setPeriodStartTime(0, TimeUnit.SECONDS)
//          //指定该任务被调度的时间
//         .setScheduleRequestedAt(0, TimeUnit.SECONDS)//当一个任务执行状态变成finish时,又没有后续的观察者来消费这个结果,那么workManager会在//内存中保留一段时间的该任务的结果。超过这个时间,这个结果就会被存储到数据库中//下次想要查询该任务的结果时,会触发workManager的数据库查询操作,可以通过uuid来查询任务的状态
//          .keepResultsForAtLeast(10, TimeUnit.SECONDS)而constraints可以设置:
//        val constraints = Constraints()
//        // 设备存储空间充足的时候才能执行. >=15%才算充足
//        constraints.setRequiresStorageNotLow(true)
//        // 必须在指定的网络条件下才能执行.不计流量(Wi-Fi)
//        constraints.requiredNetworkType = NetworkType.UNMETERED
//        // 设备电量充足. >=15%才算充足
//        constraints.setRequiresCharging(true)
//        // 必须在充电情况下才能执行
//        constraints.setRequiresCharging(true)
//        // 必须在设备空闲情况下才能被执行. 比如息屏、cpu利用率不高等。
//        constraints.setRequiresDeviceIdle(true)// workManager利用contentObserver监控传递进来的这个uri对应的内容是否发生变化,// 当且仅当它发生变化了. 我们的任务才会被触发执行,以下三个api是关联的
//        constraints.contentUriTriggers = null
//        //设置从content变化到被执行中间的延迟时间,如果在这期间。content发生了变化,延迟时间会被重新计算//这个content就是指 我们设置的setContentUriTriggers uri对应的内容
//        constraints.setTriggerContentUpdateDelay(0);
//        //设置从content变化到被执行中间的最大延迟时间//这个content就是指 我们设置的setContentUriTriggers uri对应的内容
//        constraints.setTriggerMaxContentDelay(0);// step 4.加入队列
// workRequests可以是一个请求,也可以是列表请求
val workContinuation = WorkManager.getInstance(this).beginWith(workRequests).//then()//.combine()
workContinuation.enqueue()// step 5.监听执行状态及结果
workContinuation.workInfosLiveData.observe(this) { workInfos ->// 注意:这里的onChanged方法会回调多次,// 状态:block/ running/ enqueued/ failed/ success/ finishvar completedCount = 0var failedCount = 0workInfos.forEach {val state = it.stateval outputData = it.outputDataval uuid = it.id// 拿到workRequest的idwhen (state) {WorkInfo.State.FAILED -> {if (uuid == coverUploadUUID) {InteractionPresenter.showToast("封面图上传失败")} else if (uuid == filePathUUID) {if (isVideo) {InteractionPresenter.showToast("视频上传失败")} else {InteractionPresenter.showToast("图片上传失败")}}failedCount++}WorkInfo.State.SUCCEEDED -> {val fileUrl = outputData.getString("fileUrl")// 拿到出参(也就是worker回传的数据)if (uuid == coverUploadUUID) {coverFileUrl = fileUrl} else if (uuid == filePathUUID) {fileUploadUrl = fileUrl}completedCount++}else -> {}}}// 若所有任务都执行完成,才能请求http发布帖子if (completedCount >= workInfos.size) {publishFeed()} else if (failedCount > 0) {dismissLoading()}
}

相关内容

热门资讯

“强唇劣嘴”的意思 “强唇劣嘴”的意思 成语拼音: [qiáng chún liè zuǐ] ...
“人云亦云”的意思 “人云亦云”的意思 成语拼音: [rén yún yì yún] ...
“变化无方”的意思 “变化无方”的意思 成语拼音: [biàn huà wú fāng] ...
“细高挑儿”的意思 “细高挑儿”的意思 成语拼音: [xì gāo tiǎo ér] ...
“分鞋破镜”的意思 “分鞋破镜”的意思 成语拼音: [fēn xié pò jìng] ...
“幺幺小丑”的意思 “幺幺小丑”的意思 成语拼音: [yāo mó xiǎo chǒu] ...
“谋臣武将”的意思 “谋臣武将”的意思 成语拼音: [móu chén wǔ jiàng] ...
“攒三集五”的意思 “攒三集五”的意思 成语拼音: [zǎn sān jí wǔ] ...
“虎视鹰瞵”的意思 “虎视鹰瞵”的意思 成语拼音: [hǔ shì yīng lín] ...
“逾淮为枳”的意思 “逾淮为枳”的意思 成语拼音: [yú huái wéi zhǐ] ...
“鸣珂锵玉”的意思 “鸣珂锵玉”的意思 成语拼音: [míng kē qiāng yù] ...
寻人启事 寻人启事范文(通用8篇)  寻人启事,汉语词语,发布寻人启事寻人,是失踪者及其亲友间相互寻找的一种基...
“乌合之卒”的意思 “乌合之卒”的意思 成语拼音: [wū hé zhī zú] ...
入木三分成语解释 入木三分成语解释  入木三分,是汉语的一则成语,出自唐·张怀瓘《书断·王羲之》。下面是小编为大家整理...
“逾闲荡检”的意思 “逾闲荡检”的意思 成语拼音: [yú xián dàng jiǎn] ...
形容勇敢的词语 形容勇敢的词语大全  词语,是词和短语的合称,包括词(含单词、合成词)和词组(又称短语),组成语句文...
“磨拳擦掌”的意思 “磨拳擦掌”的意思 成语拼音: [mó quán cā zhǎng] ...
小学生元旦表演什么节目好   2016年元旦晚会目创意推荐:  1、成语连珠,就是先说个成语每个组或每个人用最后一个字接成语…...
岩的成语及解释 关于岩的成语及解释大全  以“岩”字开头的成语及解释如下:  [岩穴之士] 指隐士。古时隐士多山居,...
“胸无成算”的意思 “胸无成算”的意思 成语拼音: [xiōng wú chéng suàn] ...