Android Jetpact之WorkManager

1,511 阅读3分钟

1.简介

       使用 WorkManager可以轻松地调度即使在应用退出或设备重启时仍应运行的可延迟异步任务。

功能概述:

  • 最高向后兼容到 API 14
  • 添加网络可用性或充电状态等工作约束
  • 调度一次性或周期性异步任务
  • 监控和管理计划任务
  • 将任务链接起来
  • 确保任务执行,即使应用或设备重启也同样执行任务
  • 遵循低电耗模式等省电功能

WorkManager 旨在用于可延迟运行(即不需要立即运行)并且在应用退出或设备重启时必须能够可靠运行的任务。 WorkManager 不适用于应用进程结束时能够安全终止的运行中后台工作,也不适用于需要立即执行的任务。

2.入门指南

1.创建任务-Worker

class MyWorker(appContext: Context, params: WorkerParameters) : CoroutineWorker(appContext, params) {
    
    override suspend fun doWork(): Result = coroutineScope {
        /**
         * do your work
         */
        Result.success()
    }

}

Result有三种状态:(根据具体业务逻辑返回相应的状态)

  • Result.success() - 成功
  • Result.failure() - 失败
  • Result.retry() - 重试

2.CoroutineWorker线程处理

CoroutineWorker默认工作在Dispatchers.Default。如果需要指定工作线程可进行如下操作:

class MyWorker(appContext: Context, params: WorkerParameters) : CoroutineWorker(appContext, params) {
  
    //指定IO线程,若指定主线程则指定Dispatchers.Main
    override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
        //通过getInputData()获取传入的参数
        // do your work
        Result.success()
    }
}

3.给任务进行设定

  • 约束 - Constraints
val constraints =  Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)//有网络连接时才执行任务
            .setRequiresDeviceIdle(true) //设备休眠时执行任务
            .setRequiresCharging(true)//设备充电时执行任务
             /***/还有其它的约束,可根据具体业务设置
            .build()

注意:如果指定了多个约束,任务将仅在满足所有约束时才会运行。

  • 一次性任务
 val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
            //.setInitialDelay(5,TimeUnit.MINUTES)//延迟五分钟执行
            //.setInputData(Data.Builder().build())//传入参数
            .setConstraints(constraints)//设置约束
            .build()
  • 重复性任务
//每隔15分钟执行一次
val workRequest = PeriodicWorkRequestBuilder<MyWorker>(15,TimeUnit.MINUTES)
            .build()

注意:重复性任务第一次会立即执行。下一次执行可能会提前或者延迟,取决Android的电池优化。此外任务的最小间隔为15分钟

4.监听任务状态

 WorkManager.getInstance(this).getWorkInfoByIdLiveData(workRequest.id)
            .observe(this, Observer { workInfo ->
                when (workInfo.state) {
                    WorkInfo.State.BLOCKED -> { //任务准备阶段

                    }
                    WorkInfo.State.ENQUEUED -> {//任务被添加,准备执行

                    }
                    WorkInfo.State.RUNNING -> {//任务正在执行

                    }
                    WorkInfo.State.SUCCEEDED -> {//任务执行成功

                    }
                    WorkInfo.State.CANCELLED -> {//任务被取消

                    }
                }
            })

5.获取任务进度

有时你可能需要获取任务执行的进度。需指定版本WorkManager 2.3.0-alpha01

  • 更新进度
class ProgressWorker(context: Context, parameters: WorkerParameters) :
        CoroutineWorker(context, parameters) {

        companion object {
            const val Progress = "Progress"
            private const val delayDuration = 1L
        }

        override suspend fun doWork(): Result {
            val firstUpdate = workDataOf(Progress to 0)//开始的进度
            val lastUpdate = workDataOf(Progress to 100)//结束的进度
            setProgress(firstUpdate)
            /*
            * do your work
            */
            setProgress(lastUpdate)
            return Result.success()
        }
    }
  • 监听进度
 WorkManager.getInstance(applicationContext)
        .getWorkInfoByIdLiveData(workRequest.id)
        .observe(observer, Observer { workInfo: WorkInfo? ->
                if (workInfo != null) {
                    val progress = workInfo.progress //获取Progress对象
                    val value = progress.getInt(Progress, 0)//获取进度值
                   
                }
        })

6.执行任务

  • 执行单个任务
WorkManager.getInstance(application).enqueue(workRequest)
  • 执行组合任务
 WorkManager.getInstance(myContext)
        // 参数可以是单个任务,也可以是一个集合
        .beginWith()
        //前往的任务执行完后,开始执行此任务
        .then(compress)
        .then(upload)//最后执行的任务
        .enqueue()
  • 策略性执行任务
//策略性执行一次性任务
WorkManager.getInstance(application).enqueueUniqueWork("upload",ExistingWorkPolicy.REPLACE,workRequest)
//策略性执行周期任务
WorkManager.getInstance(application).enqueueUniquePeriodicWork("refresh",
                                                        ExistingPeriodicWorkPolicy.REPLACE,
                                                        workRequest.id)

  • ExistingWorkPolicy.REPLACE - 如果已经存在相同唯一名称的任务,会把之前的任务取消并删除(如果任务还未完成)。然后插入新指定的同名任务。
  • ExistingWorkPolicy.KEEP - 同名任务都会被保留。
  • ExistingWorkPolicy.APPEND - 如果已经存在同名任务,如果之前的任务还未完成,则新加入的同名任务会被附加之前任务的后面执行。

7.取消任务

WorkManager.getInstance(application).cancelWorkById(workRequest.id)