Android Jetpack 系列篇(二) WorkManager

本篇文章介绍 Jetpack 架构组件中的 WorkManager, 该组件可以灵活管理 Android 后台任务

主要特点

  1. 向后兼容API 14,在API 23+的设备上使用JobScheduler,在具有API 14-22的设备上使用BroadcastReceiver + AlarmManager的组合
  2. 可以设置网络状态或计费状态等约束条件
  3. 实现异步一次性或定期任务
  4. 有效监控和管理计划任务
  5. 实现多个任务并行或串行执行
  6. 应用程序或设备重新启动也可确保任务执行
  7. 保持Doze模式等省电功能
  8. 可以将日志或分析发送到后端服务
  9. 可以定期将应用程序数据与服务器同步

组成部分

主要由这几部分组成:Worker、WorkRequest、Constraints、WorkManager、WorkContinuation

Worker 一个任务处理的对象,专注于处理后台耗时操作,并且可以灵活接收参数和返回结果

也是一个抽象类,有一个抽象方法doWork(),所有逻辑耗时操作都可以在这个方法里执行,如果执行成功可以返回Result.success(), 失败返回Result.failure(), 重试返回Result.retry(),返回结果时可以在成功或失败中传递,如:Result.success(data)

WorkRequest 任务请求对象

同样是一个抽象类,系统给我们提供了两个实现类,OneTimeWorkRequestPeriodicWorkRequest, 前者是一次任务,后者为循环任务。可以安排要执行的任务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

你可能感兴趣的:(Android,学习)