Android 玩转WorkManager(一)

353 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

Android 玩转WorkManager(一)

WorkManager 是Android JetPack库中的成员之一,主要用作处理后台任务,它可以允许你创建一个立即运行或者是在给定条件下触发的任务,WorkerManger有一个持久化特性就是WorkManger在底层使用了Room来保证进程被结束或者是设备重启后,任务任然可以重新执行。并且WorkManager可以设置一个任务链,在上一个任务执行完成之后会自动执行下一个在链中排队的任务

WorkManager导航架构图

img

WorkerManger中主要有以下组成:

WorkManger:接收带参数和约束条件的WorkRequest,并将其排入队列
Worker:任务队列的最小执行单位,需要实现doWork()方法,它是执行在一个单独的后台进程中,所有需要在后台执行的任务都         在这个方法内完成
WorkRequest:给Worker设置参数和约束条件等,比如联网触发任务等worker执行触发条件都是可以通过它来设置
WorkResult: Worker的执行结果只要包含 Success, Failure, Retry 
WorkStatus: workerManager为Request提供了一个LiveData,通过LiveData来获取当前任务的执行状态

WorkManger

WorkManger工作流程

img

 //可以从源码看出在Api >= 23的时候底层是使用JobScheduler来实现的任务调度服务  
public static final int MIN_JOB_SCHEDULER_API_LEVEL = 23;
@NonNull
static Scheduler createBestAvailableBackgroundScheduler(
 @NonNull Context context,
 @NonNull WorkManagerImpl workManager) {
 Scheduler scheduler;
      if (Build.VERSION.SDK_INT >= WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL) {
            scheduler = new SystemJobScheduler(context, workManager);
            setComponentEnabled(context, SystemJobService.class, true);
            Logger.get().debug(TAG, "Created SystemJobScheduler and enabled SystemJobService");
        } else {
            //设备是否能访问Google Play Services 不能就使用AlarmManager来实现
            scheduler = tryCreateGcmBasedScheduler(context); 
            if (scheduler == null) {
                scheduler = new SystemAlarmScheduler(context);
                setComponentEnabled(context, SystemAlarmService.class, true);
                Logger.get().debug(TAG, "Created SystemAlarmScheduler");
            }
        }
     return scheduler;
}

WorkManger主要作用:对WorkRequest进行管理,包括执行,控制,取消,观察执行消息

//通过enqueue()将quest加入到任务队列
WorkManager.getInstance().enqueue(workerRequest)
//观察指定的worker的执行状态 getWorkInfoByIdLiveData()该方法会返回一个Livedata
workManager.getInstance().getWorkInfoByIdLiveData(workerRequest.id)
//可以通过一些Api构建任务链
/**
 * 
 *                          workerRequest1
 *                                |
 *                       +---------
 *                workerRequest2         
 *                       |
 *               +--------------+
 *               |              |
 *        workerRequest3   workerRequest4  
 */
workManager.getInstance()
		  .beginWith(workerRequest1) //添加起始任务
		  .then(workerRequest2)      //workerRequest1执行完毕之后执行单个任务workerRequest2
		  .then(listof(workerRequest3,workerRequest4)) // workerRequest2 执行任务列表
		  .enqueue()

Worker

Worker主要分为两类:一次性Worker(OneTimeWorkRequest) 和周期性Worker(PeriodicWorkRequest)

Worker生命周期图:

一次性工作的状态

public enum State {
//用于指示当WorkRequest的Constraints被满足并且资源可用时,WorkRequest被排队并且有资格运行。
ENQUEUED,
// 用于指示工作请求当前正在执行
RUNNING,
/**
  *用于指示WorkRequest已在成功状态下完成。注意,PeriodicWorkRequests永远不会进入这种状态(它们将简单地返回到     * ENQUEUED并且有资格再次运行)。
  */
SUCCEEDED,
//用于指示WorkRequest已在失败状态下完成。所有相关的工作也将被标记为#FAILED,并且永远不会运行。
FAILED,
//用于指示WorkRequest当前被阻塞,因为它的先决条件还没有成功完成。
BLOCKED,
//用于指示WorkRequest已被取消且不会执行。所有相关的工作也将被标记为#CANCELLED,并且不会运行。
CANCELLED;

public boolean isFinished() {
    return (this == SUCCEEDED || this == FAILED || this == CANCELLED);
}

SUCCEEDED、FAILED 和 CANCELLED 均表示此工作的终止状态。

如果您的工作处于上述任何状态WorkInfo.State.isFinished() 都将返回 true。下图如果worker设置了重试回退策略,在Worker运行的时候如果返回retry() 此时就会进行回退策略

img

周期性工作的状态

img

怎么创建Worker?

class PrintWorker constructor(
    val context: Context,
    val workerParameters: WorkerParameters
) : Worker(context, workerParameters) {
      override fun doWork(): Result {
           //需要执行的工作
      } 
}
/**
*1、除了可以使用Java实现的Worker之外还可以使用kotlin实现的CoroutineWorker
*2、CoroutineWorker会自动帮你处理任务的暂停和取消 该协程默认实在Dispatchers.Default上启动 可以使用*withContext()进行配置
*3、与Worker不同CoroutineWorker中的代码不会再WorkManager的Configuration 中指定的 Executor 上运行。
*/
class PrintWorker constructor(
    val context: Context,
    val workerParameters: WorkerParameters
) : CoroutineWorker(context, workerParameters) {
      override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
           //需要执行的工作
      } 
}


WorkRequest

WorkRequest中包含了WorkManager对WorkRequest对其进行调度和运行工作所需的所有信息,比如工作的约束条件,回退策略,回退基数,延时启动等配置信息

//传入数据
val data = Data.Builder().pusString("key","value").build()
/**********************约束条件************************/
val constrains = Constraints.Builder()
constrains.setRequiresDeviceIdle(true)//如果我们想让它在进入 Doze 模式时工作,我们只需要将其设置为 true
constrains.setRequiresNetworkType(NetWorkType.CONNECTED) // 我们可以设置互联网连接状态。
constrains.setRequiresBatteryNotLow(true) //如果电池电量不低,我们可以设置它的状态。默认值为假。
constrains.setRequiresCharging(true)  //插入状态。默认值为假。

val workRequest = OneTimeWorkRequest.Builder(OneTimeWorker::class.java)
					.setConstraints(constrains) //设置约束
		  			.setInputData(data) //设置传入数据
					.setInitialDelay(20,TimeUnit.SECONDS)
//worker中的doWork()方法通过inputData获取传入数据
do work(){
    
}