WorkManager使用记录

以下代码是用Java语言编写的,也并没有兼容AndroidX,如果项目兼容AndroidX的话,WorkManager实例的获取是有点区别的,Kotlin就可以去官网了,大概原理差不多,以下资料来源于官网文档,正好先用到一点,当做笔记记录一下。


内容一览:

  • 用途、优点、添加依赖、用法思路

  • 创建后台任务类、配置WorkManager请求参数以及执行

  • 定义任务约束、任务延迟执行

  • 定义任务的输入和输出、为任务添加标签、取消任务

  •  后台任务状态的监听

  •  设定一次只能激活一个特定名称的后台任务


用途

属于JetPack结构组件,用于进行后台任务



优点

操作简单,稳定性强,对于异步任务,即使APP退出运行或者设备重启,都能很好的保证任务的顺利执行


添加依赖

implementation  "android.arch.work:work-runtime:1.0.1"   (Java)

 



用法思路:

新建一个类继承Woker,并实现其方法,在其doWork()方法中进行后台任务,然后再根据返回的状态对任务结果进行相应的处理
    



创建后台任务类:


    

Class DemoWorker extends Worker {
        public DemoWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
            super(context, workerParams);
        }
    }
    
    @NonNull
    @Override
    public Result doWork() {
        //在这里进行后台任务
        
        return Result.success(); //此处返回值下面讲述
    }


    doWork()方法的返回值
    Result.success():已成功完成
    Result.failure() : 已失败文
    Result.retry():稍后重试
    



配置WorkManager请求参数以及执行
    

构建一次性任务(只执行一次,执行完就自动结束)


    /**
     * OneTimeWorkRequest : 专门用于构建一次性任务
     * DemoWorker: 指的是当前创建的后台任务类名称 
     */
    OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(DemoWorker.class).build();


 构建周期性任务(只隔一个周期执行一次,执行完就自动结束,周期间隔至少为15分钟)

   /**
     * PeriodicWorkRequest : 专门用于构建周期性任务
     * 15 :计数单位
     * TimeUnit.MINUTES : 以分钟为计时单位
     * DemoWorker: 指的是当前创建的后台任务类名称 
     */
     PeriodicWorkRequest request = new PeriodicWorkRequest.Builder(DeviceSyncWorker.class, 15, TimeUnit.MINUTES)
                .build();


 执行任务:(通过enqueue方法执行任务)

  WorkManager.getInstance().enqueue(request);

 

定义任务约束:


 添加约束:网络连接

Constraints constraints = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();


然后将constraints加入任务构建中,例如:

 OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(DemoWorker.class)
        .setConstraints(constraints)
        .build();
    


    约束的种类:
        addContentUriTrigger:
        setRequiredNetworkType:网络连接状态约束(需要网络,不需要网络,不限时的网络,非漫游网络,计量网络连接)
        setRequiresBatteryNotLow:设备电池电量处于可接受的水平才可以执行任务
        setRequiresCharging:设备充电时才可以执行任务
        setRequiresDeviceIdle:设备空闲状态时才可以执行任务
        setRequiresStorageNotLow:设备存储处于可接受的范围才可以执行任务
        setTriggerContentMaxDelay:设置从第一次检测到内容更改到计划的时间所允许的最大延迟
        setTriggerContentUpdateDelay:设置从第一次检测到内容更改到计划的时间所允许的延迟
  


     
任务初始延迟:


 如果不希望任务立即执行,则可以将任务指定为在经过最短的初始延迟后启动,例如:

OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(DemoWorker.class)
            .setInitialDelay(10, TimeUnit.MINUTES)
            .build();

 

定义任务的输入和输出


    使用场景:任务需要数据以传入参数的形式传入,或者将数据返回为结果(
    注意:Data 对象应该很小,值可以是字符串、基元类型或数组变体。
         如果需要将更多数据传入和传出工作器,应该将数据放在其他位置,例如 Room 数据库。Data 对象的大小上限为 10KB。
    例如:(此处是官方的例子)
    场景是:后台任务是处理图像上传,要求以要上传图片的URL为输入,并且要求用已上传图像的网址作为输出
    代码如下:
    
  

 /**
     * Constants.KEY_IMAGE_URI :自定义的字符串常量
     * imageUriString:要上传的图片URL
     * UploadWorker:后台任务类的名称
     */
    Data imageData = new Data.Builder
                    .putString(Constants.KEY_IMAGE_URI, imageUriString)
                    .build();

    OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadWorker.class)
            .setInputData(imageData)
            .build()
    
    
    输入的Data数据可在doWork()方法中进行获取,例如:
    @NonNull
    @Override
    public Result doWork() {
        
        String dataInput = getInputData().getString(Constants.KEY_IMAGE_URI);
        
        //后台任务返回数据  uploadFile(dataInput)====>>> 后台任务
        举例: Response response = uploadFile(dataInput)
        
        //将后台任务返回的数据中取出要返回的数据,放入Data中
        Data outputData = new Data.Builder
                    .putString(Constants.KEY_IMAGE_URI, response.imageUrl)
                    .build();
        
        return Result.success(outputData); 
    }

 

为任务添加标签


    添加标签的好处:通过标签来取消后台任务请求(可以将同一标签下所有的后台任务请求全部取消)
    例如:

添加标签:
    OneTimeWorkRequest cacheCleanupTask = new OneTimeWorkRequest.Builder(DemoWorker.class)
        .setConstraints(constraints)
        .addTag("cleanup")
        .build();
通过标签取消任务:
    WorkManager.getInstance().cancelAllWorkByTag("cleanup");


取消任务:

通过ID取消指定单个任务:
        WorkManager.getInstance().cancelWorkById(request.id);
通过标签取消标签名下的所有任务:
        WorkManager.getInstance().cancelAllWorkByTag("cleanup");
一次性取消全部任务:
        WorkManager.getInstance().cancelAllWork();

 

后台任务状态的监听:


    通过id监听单个后台任务请求的运行结果:

WorkManager.getInstance(myContext).getWorkInfoByIdLiveData(uploadWorkRequest.getId())
            .observe(lifecycleOwner, new Observer() {
                @Override
                public void onChanged(@Nullable WorkInfo workInfo) {
                  if (workInfo != null && workInfo.state == WorkInfo.State.SUCCEEDED) {
                      Log.e(TAG,"Success");
                  }
                }
            });


    
    通过Tag标签监听同一标签下所有后台任务请求的运行结果:

 WorkManager.getInstance().getWorkInfosByTagLiveData("tag").observe(this, new android.arch.lifecycle.Observer>() {
            @Override
            public void onChanged(@Nullable List workInfos) {
                for (WorkInfo workInfo : workInfos) {
                    if (workInfo != null && workInfo.getState() == WorkInfo.State.SUCCEEDED) {
                        Log.e(TAG,"Success");
                    }
                }
            }
        });


    如果后台任务执行是通过enqueueUniqueWork(“workName")执行的,可以通过getWorkInfosForUniqueWorkLiveData监听后台任务运行结果:

WorkManager.getInstance().getWorkInfosForUniqueWorkLiveData("workName").observe(this, new android.arch.lifecycle.Observer>() {
            @Override
            public void onChanged(@Nullable List workInfos) {
                if (workInfos == null) {
                    Log.e(TAG,"Success");
                    return;
                }
                for (WorkInfo workInfo : workInfos) {
                    if (workInfo != null && workInfo.getState() == WorkInfo.State.SUCCEEDED) {
                        Log.e(TAG,"Success");
                    }
                }
            }
        });    

设定一次只能激活一个特定名称的后台任务

  /**
     * enqueueUniqueWork:通过此方法设定一次只能激活一个特定名称的后台任务
     * singleWork:进行此操作的唯一名称,之后状态监听要获取此名称
     * ExistingWorkPolicy:工作策略(REPLACE:取消现有的序列并用新序列替换   KEEP:保持现有顺序并忽略新的请求  
                             APPEND:将新序列附加到现有学列,在现有序列的最后一个任务完成后运行新序列的第一个任务)
     * request:自行构建的一次性任务或者周期性任务
     * 如何监听此任务状态,上述有代码
     */
    WorkManager.getInstance().enqueueUniqueWork("singleWork", ExistingWorkPolicy.KEEP, request);

 


开启链式任务


注意:WorkerManager要求必须在前一个后台任务运行成功后,下一个后台任务才会运行,也就是说,如果某个后台任务运行失败,或者被取消了,那么接下来的后台任务就都得不到运行了。


比如我们有A,B,C三个任务,我们需要顺序执行。那我们就可以

使用beginWith()方法用于开启一个链式任务(任务允许重复),后面接上后台任务,可使用then()方法链接即可;

WorkManager.getInstance().beginWith(A).then(B).then(C).enqueue();


使用beginUniqueWork()方法用于开启一个链式任务(任务不允许重复)

WorkManager.getInstance().beginUniqueWork("unique", ExistingWorkPolicy.KEEP, requestA)
                   .then(requestB)
                   .then(requestC)
                   .enqueue();


beginWith(),beginUniqueWork()两个函数开启的队列的唯一区别在于,队列里面的任务能不能重复。
beginWith()开始的队列里面的任务是可以重复的,beginUniqueWork()开始的队列里面的任务是不能重复的。

 


 

如果小伙伴发现书写中出现错误,或者有更好的封装办法,欢迎留言和私信。

你可能感兴趣的:(常用框架)