WorkerManager 的基本使用


文章目录

  • 一、相关类
  • 二、使用
  • 三、执行简单说明
  • 四、定时调度任务
  • 五、指定条件下执行任务
  • 六、延时调度任务
  • 七、Result.retry() 重试和退避
  • 八、标记任务和数据的传入


一、相关类
  • Worker:自定义或继承实现该类,doWork() 方法中为执行的任务;
  • WorkerRequest:保存相关 Worker 的请求。
  • WorkManager:进行任务执行。
二、使用
  1. 添加依赖
  2. 自定义 Worker 任务
public class MyWorker extends Worker {

    private final String TAG = "MyWorker";
    Map value;

    public MyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
        Data inputData = workerParams.getInputData();
        this.value = inputData.getKeyValueMap();
    }

    @NonNull
    @Override
    public Result doWork() {
        String a = (String) value.get("value");
        Log.d(TAG,"a的值为:" + a);

        if("success".equals(a)) {
            Log.d(TAG,"成功, a value:" + a);
            return Result.success();
        } else if("failure".equals(a)) {
            Log.d(TAG,"失败, a value:" + a);
            return Result.failure();
        }
        Log.d(TAG,"重试, a value:" + a);
        return Result.retry();
    }
}
  1. 创建 WorkRequest
HashMap<String,String> inputData = new HashMap(3);
inputData.put("value","success");

//数据传递,最好使用 Data.Builder() 构建,这是图省事
@SuppressLint("RestrictedApi")
Data data = new Data(inputData);
//创建携带数据的请求
WorkRequest request = new OneTimeWorkRequest.Builder(MyWorker.class)
        .setInputData(data)
        .build();
  1. 使用 WorkManager 提交 Work
WorkManager.getInstance(this).enqueue(request);
  1. 执行结果 Log(OneTimeWorkRequest 请求结果,不要混淆其他方式的请求)
D/MyWorker: a的值为:success
D/MyWorker: 成功, a value:success
D/MyWorker: a的值为:failure
D/MyWorker: 失败, a value:failure
D/MyWorker: a的值为:retry
D/MyWorker: 重试, a value:retry

D/MyWorker: a的值为:success
D/MyWorker: 成功, a value:success
D/MyWorker: a的值为:failure
D/MyWorker: 失败, a value:failure

D/MyWorker: a的值为:retry
D/MyWorker: 重试, a value:retry
D/MyWorker: a的值为:retry
D/MyWorker: 重试, a value:retry
D/MyWorker: a的值为:retry
D/MyWorker: 重试, a value:retry
  1. 请求类型
  • OneTimeWorkRequest:不会循环、重复执行任务的请求。会根据策略进行任务重试,区分好重试循环执行的区别。
  • PeriodicWorkRequest:可能重复、循环执行任务的请求。类似定时调度这些就是,也会根据重试策略去重试任务的执行。(注意发生错误时重试循环执行两者之间有可能发生冲突)
  • 自定义请求:继承抽象类 WorkRequest,根据需求定义。
三、执行简单说明
  1. Worker.doWork() 返回值
  • Result.success:任务执行成功。
  • Result.failure():任务执行失败。
  • Result.retry():任务执行失败,根据重试策略进行重试。
  1. WorkRequest 相关:
  • OneTimeWorkRequest:执行一次,加急调用 WorkRequest.setExpedited() 方法;无序配置使用 from();较为复杂用 build()
WorkRequest request = new OneTimeWorkRequest.from(MyWork.class);//无需配置
WorkRequest request = new OneTimeWorkRequest.Builder(MyWork.class).build();//较为复杂的工作
  1. 对任务进行加急,加急的特征:
  • 重要性:加急适用于对用户很重要或由用户启动的任务。
  • 速度:加急工作最适合那些立即启动并在几分钟内完成的简短任务。
  • 配额:限制前台执行时间的系统级配额决定了加急任务是否可以启动。
  • 电源管理:电源管理限制(如省电模式和低电耗模式)不太可能影响加急工作。
  • 延迟时间:系统立即执行加急工作,前提是系统的当前工作负载允许执行此操作。这意味着这些任务对延迟事件较为敏感,不能安排到以后执行。
    配额说明:系统必须为加急任务分配应用执行事件,才能执行任务。执行时间受到配额限制,当上一个加急任务未完成分配时间的执行或任务完成的话,下一个加急任务不会执行。配额只有在应用处于后台才起效,应用处于前台无限制。
  • 加急要求:WorkManager 2.7 以上,所有的 ListenableWorker 都必须实现 getForegroundInfo 方法。
  • 加急要求二------信息获取:在 Android12 以下的Android 上,执行任务的 WorkManager 需实现 getForegroundInfoAsync() 方法,该方法可获得加急信息。Android12 以上不用实现。
  • 加急使用,构建 Request 时调用 setExpedited() 即可:
OneTImeWorkRequest request = new OneTimeWorkRequestBuilder<T>()
.setInputData(inputData)
.setExpedited(OutOfOuotaPolicy.RUN_AS_NON_EXPEDITED_WORKER_REQUEST)
.build();//加急执行

参数说明:

  • OutOfOuotaPolicy.RUN_AS_NON_EXPEDITED_WORKER_REQUEST:任务作为普通任务执行。
  • OutOfOuotaPolicy.DROP_WORK_REQUEST:配额不足是导致请求取消。
四、定时调度任务

简单使用 PeriodicWorkRequest 类完成定时调度

  1. 重复调度(说明:最短时间间隔为 15 分钟)
    每隔一小时调度一次:
PeriodicWorkRequest request = new PeriodicWorkRequest.
        Builder(MyWorker.class,1,TimeUnit.HOURS)
                .build();//一小时间隔定时调度

参数说明

  • 参数一 MyWorker.Class:自定义 Worker。
  • 参数二 1:数值。
  • 参数三 TimeUnit.HOURS:参数二的单位–小时。
  1. 灵活调度(间隔时间大于等于五分钟)
    每个小时最后十五分钟调度一次:
PeriodicWorkRequest request = new PeriodicWorkRequest.
        Builder(MyWorker.class,1,TimeUnit.HOURS,
                        15,TimeUnit.MINUTES)
                .build();//每个小时的最后十五分钟进行调度
五、指定条件下执行任务
  1. 使用类 Constraints 完成约束,setConstraints() 包装约束
Constraints constraints = new Contraints.Builder()
        .setRequiredNetworkType(NetworkType.UNMETERED)
        .setRequiresCharging(true)
        .build();//当网络为 Wifi,设备充电时才会进行调度
WorkRequest request = new OneTimeWorkRequest.Builder(MyWork.class)
        .setConstraints(constraints)
        .build();//建立请求
WorkManager manager = WorkManager.getInstance().enqueue(request);//任务调度

调度参数说明:

属性

说明

NetworkType

约束任务执行的网络类型,如Wifi(UNMETERED)

BatteryNotLow

如果设置为 true,当设备处于“电量不足模式”时,任务不会i执行

RequiresCharging

如果设置为 true,那只有在设备充电时,任务才会调度执行

Deviceldle

如果设置为 true,则要求用户的设备处于空闲状态才能执行任务。该约束适用于执行批量任务时;若是不使用该约束,批量操作可能会导致用户设备上正在运行的其他应用的性能

StorageNotLow

如果设置为 true,当用户设备上的存储空间不足时,任务不会调度执行

执行时期若条件未满足,该任务会停止调度,而不是继续执行。

六、延时调度任务

使用 setInitiaDelay() 进行延时调度。

WorkRequest request = new OneTimeWorkRequest(MyWork.class)
        .setInitialDelay(10,TimeUnit.MINUTES)
        .build();//加入调度队列后至少10分钟再执行

执行依旧受约束条件和系统限制。

七、Result.retry() 重试和退避
  1. setBackoffCriteris() 基本使用(说明:重试会与设置相差几秒,但不会低于初始退避延迟时间)
WorkRequest request =
       new OneTimeWorkRequest.Builder(MyWork.class)
               .setBackoffCriteria(
                       BackoffPolicy.LINEAR,
                       OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
                       TimeUnit.MILLISECONDS)
               .build();//第一次重试10秒,每次重试时,重试间隔会依次增加 10 秒直至成功执行

说明:

  • BackoffPolicy.LINEAR:退避策略。每次重试时间间隔为 上一次时间+最短退避延迟时间。若为 BackoffPolicy.EXPONENTIAL ,则此次重试时间间隔为 上次时间间隔乘以2。
  • OneTimeWorkRequest.MIN_BACKOFF_MILLIS:最短退避延迟时间。初始重试时间的间隔。
  • TimeUnit.MILLISECONDS:单位,此处为秒。
八、标记任务和数据的传入
  1. 任务标记
    任务标记可以帮助查看任务情况(可标记多次):
WorkRequest request =
       new OneTimeWorkRequest.Builder(MyWork.class)
       .addTag("tag")
       .build();//添加标记为 tag
WorkInfo info = WorkManager.getWorkInfosByTag(String tag);//返回含有该 tag 的 WorkInfo
info.getTags();//获取 Work 的所有 tag
WorkManager.cancelAllWorkByTag(String tag);//取消含有 tag 标记的所有任务请求
  1. 向 Worker 传入数据并获取
    WorkRequest.setInputData(Data data) 传入数据,Worker.getInputData.getXXX(String key)获取数据。
// 自定义 Worker 并获取数据
public class MyWorker extends Worker {

   public MyWorker(Context appContext, WorkerParameters workerParams) {
       super(appContext, workerParams);
   }

   @NonNull
   @Override
   public Result doWork() {
       String msg = getInputData().getString("msg");
       if(msg == null) {
           return Result.failure();
       }
       //使用数据进行操作
       return Result.success();
   }
}
// 创建请求并传入数据
WorkRequest myUploadWork =
      new OneTimeWorkRequest.Builder(UploadWork.class)
           .setInputData(
               new Data.Builder()
                   .putString("msg", "这是信息值")
                   .build()
           )
           .build();

Data 以 ket-valus 形式存储,获取使用 key 即可。