本篇文章介绍 Jetpack 架构组件中的 WorkManager, 该组件可以灵活管理 Android 后台任务
主要由这几部分组成:Worker、WorkRequest、Constraints、WorkManager、WorkContinuation
Worker 一个任务处理的对象,专注于处理后台耗时操作,并且可以灵活接收参数和返回结果
也是一个抽象类,有一个抽象方法doWork()
,所有逻辑耗时操作都可以在这个方法里执行,如果执行成功可以返回Result.success()
, 失败返回Result.failure()
, 重试返回Result.retry()
,返回结果时可以在成功或失败中传递,如:Result.success(data)
。
WorkRequest 任务请求对象
同样是一个抽象类,系统给我们提供了两个实现类,OneTimeWorkRequest
和PeriodicWorkRequest
, 前者是一次任务,后者为循环任务。可以安排要执行的任务Builder()
、设置执行条件setConstraints()
、传递任务需要的参数setInputData()
Constraints 任务执行条件对象
设置网络状态setRequiredNetworkType()
设置电量低是否执行setRequiresBatteryNotLow()
设置充电时是否执行setRequiresCharging()
设置存储容量不足是否执行setRequiresStorageNotLow()
】
WorkManager 任务管理对象,通过该对象可以对任务进行预开始、监听、取消等操作
预开始任务操作beginWith()
获取任务LiveData对象getWorkInfoByIdLiveData()
取消操作cancelWorkById()
WorkContinuation 任务的延续对象,通过该对象可以对任务组合执行
连接任务操作then()
并行连接操作combine()
执行操作enqueue()
创建一个CompressWorker
, 只打印了一句话,然后返回成功
class CompressWorker(context : Context, params : WorkerParameters): Worker(context, params) {
override fun doWork(): Result {
Logger.d("doWork....")
// Indicate success or failure with your return value:
return Result.success()
}
}
指定任务执行条件
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED) // 网络状态
.setRequiresBatteryNotLow(true) // 不在电量不足时执行
.setRequiresCharging(true) // 在充电时执行
.setRequiresStorageNotLow(true) // 不在存储容量不足时执行
.setRequiresDeviceIdle(true) // 在待机状态下执行,需要 API 23
.build()
创建任务
// 一次任务 设置条件
val workA = OneTimeWorkRequest.Builder(CompressWorker::class.java).setConstraints(constraints).build()
// 一次任务 传递参数
val workB = OneTimeWorkRequest.Builder(MathWorker::class.java)
.setInputData(Data.Builder()
.putInt(MathWorker.KEY_X_ARG, 1)
.putInt(MathWorker.KEY_Y_ARG, 2)
.putInt(MathWorker.KEY_Z_ARG, 3)
.build())
.build()
// 多次任务 间隔30分钟执行一次, 最小限制为15分钟,和 JobScheduler API 限制一样
val workC = PeriodicWorkRequest.Builder(CompressWorker::class.java, 30, TimeUnit.MINUTES).build()
MathWorker
类
class MathWorker(context : Context, params : WorkerParameters) : Worker(context, params) {
companion object {
// Define the parameter keys:
const val KEY_X_ARG = "X"
const val KEY_Y_ARG = "Y"
const val KEY_Z_ARG = "Z"
// ...and the result key:
const val KEY_RESULT = "result"
}
override fun doWork(): Result {
val x = inputData.getInt(KEY_X_ARG, 0)
val y = inputData.getInt(KEY_Y_ARG, 0)
val z = inputData.getInt(KEY_Z_ARG, 0)
// ...do the math...
val result = myCrazyMathFunction(x, y, z)
//...set the output, and we're done!
val output: Data = Data.Builder().putInt(KEY_RESULT, result).build()
return Result.success(output)
}
private fun myCrazyMathFunction(x: Int, y: Int, z: Int): Int{
return x + y + z
}
}
监听任务
WorkManager.getInstance().getWorkInfoByIdLiveData(workA.id)
.observe({ lifecycle }, { workInfo ->
// Do something with the status
if (workInfo != null && workInfo.state.isFinished) {
Logger.d("workA")
}
})
WorkManager.getInstance().getWorkInfoByIdLiveData(workB.id)
.observe({ lifecycle }, { workInfo ->
// Do something with the status
if (workInfo != null && workInfo.state.isFinished) {
//获取 MathWorker 返回的数据
Logger.d("workE="+workInfo.outputData.keyValueMap[MathWorker.KEY_RESULT])
}
})
WorkManager.getInstance().getWorkInfoByIdLiveData(workC.id)
.observe({ lifecycle }, { workInfo ->
// Do something with the status
Logger.d("workInfo="+workInfo?.state)
if (workInfo != null && workInfo.state.isFinished) {
Logger.d("workInfo="+workInfo.id)
}
})
执行任务
//单个任务执行
WorkManager.getInstance().enqueue(workA)
//多个任务串行
WorkManager.getInstance().beginWith(workA).then(workB).enqueue()
//workA和workB并行执行后,再执行workC
WorkManager.getInstance().beginWith(listOf(workA, workB)).then(workC).enqueue()
//workA和workB串行,workC和workD串行,chain1和chain2并行
val chain1 = WorkManager.getInstance().beginWith(workA).then(workB)
val chain2 = WorkManager.getInstance().beginWith(workC).then(workD)
WorkContinuation.combine(listOf(chain1, chain2)).enqueue()
取消任务
WorkManager.getInstance().cancelWorkById(workA.id)
WorkManger 介绍就到这里了,更多详细信息,可以查看官方文档: https://developer.android.com/topic/libraries/architecture/workmanager