Android Jetpack之WorkManager使用详解

简介

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

可用于确保重要的后台任务一定会执行,比如上传,下载,同步服务器等操作

B站官方视频:https://www.bilibili.com/video/av56276889

主要功能

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

WorkManager 旨在用于可延迟运行(即不需要立即运行)并且在应用退出或设备重启时必须能够可靠运行的任务。例如:

  • 向后端服务发送日志或分析数据
  • 定期将应用数据与服务器同步

WorkManager 不适用于应用进程结束时能够安全终止的运行中后台工作,也不适用于需要立即执行的任务。请查看后台处理指南,了解哪种解决方案符合您的需求。

配置Build.gradle文件

dependencies {
  def work_version = "2.4.0"

    // (Java only)
    implementation "androidx.work:work-runtime:$work_version"

    // Kotlin + coroutines
    implementation "androidx.work:work-runtime-ktx:$work_version"

    // optional - RxJava2 support
    implementation "androidx.work:work-rxjava2:$work_version"

    // optional - GCMNetworkManager support
    implementation "androidx.work:work-gcm:$work_version"

    // optional - Test helpers
    androidTestImplementation "androidx.work:work-testing:$work_version"
  }

创建后台任务

任务是使用 Worker 类定义的。doWork() 方法在 WorkManager 提供的后台线程上同步运行。

要创建后台任务,请扩展 Worker 类并替换 doWork() 方法。例如:

伪代码

MainActivity extends AppCompatActivity {

   private static final String TAG = "MainActivity";


onCreate(){

  //定义传入到任务中的数据
  Data inputData = new Data.Builder().putString(TAG, "我想知道你的名字").build();

  //OneTimeorkRequest的初始化
  request=new OneTimeWorkRequest.Builder(MyWorker.class)
                .setInputData(inputData)
                .build();
  //把任务加入到任务队列中,并在满足某种条件的情况去执行
   WorkManager.getInstance().enqueue(request);

   //订阅获取回传的数据
  WorkManager.getInstance().getStatusById(request.getId())
            .observe(this, new Observer() {
                @Override
                public void onChanged(WorkStatus workStatus) {
                    if(workStatus !=null && workStatus.getState().isFinished()){
                        //在任务执行完成后
                        Log.i(TAG,"activity取到了回传的数据--- "+workStatus.getOutputData().getString("name"));
                    }
                }
            });
}

}


public class MyWorker extends Worker {
    //这个方法是在子线程执行的
    private static final String TAG = "MyWorker";
    @NonNull
    @Override
    public Result doWork() {
        //上传,下载,同步数据。。。。。。
        Log.i(TAG,"work执行了");
        //获取mainActivity传入进来的数据
        String jettData=getInputData().getString("MainActivity");
        Log.i(TAG,"work中取到了----- "+jettData);
        //把任务中的数据回传到activity中
        Data outputData = new Data.Builder().putString("name", "老张").build();
        setOutputData(outputData);
        return Result.SUCCESS;
    }
}


执行结果如下

Android Jetpack之WorkManager使用详解_第1张图片

 

添加执行条件Constraints

  //构建限制条件 为了方便测试这里只加充电
        Constraints constraints = new Constraints.Builder()
               // .setRequiredNetworkType(NetworkType.CONNECTED) //网络状态
                //.setRequiresBatteryNotLow(true) //不是低电量
                //.setRequiresDeviceIdle(true)//设备待机空闲
                //.setRequiresStorageNotLow(true)//内存不紧张
                .setRequiresCharging(true) //充电
                .build();


    request=new OneTimeWorkRequest.Builder(MyWorker.class)
                .setInputData(inputData)
                .setConstraints(constraints)//设置条件
                .build();

添加条件要注意如果第一个条件不满足,那么会间隔10分钟再去判断限制条件执行

Android Jetpack之WorkManager使用详解_第2张图片

为什么说是10分钟呢,经过一番查找 找到源码如下

Android Jetpack之WorkManager使用详解_第3张图片

多任务执行

  /*1.顺序执行
        *   [request1]
        *       ↓
        *   [request2]
        *       ↓
        *   [request3]
        *
        * */
        WorkManager.getInstance()
                .beginWith(request1)
                .then(request2)
                .then(request3)
                .enqueue();
        //2.分支执行
        /*
        *  [request1]     [request1]
        *       ↘           ↙
        *         ↘       ↙
        *             ↓
        *         [request3]
        * */
        WorkManager.getInstance()
               .beginWith(request1,request2)
               .then(request3)
                .enqueue();

        //3.多任务链方式
        /*
         *  [request1]     [request4]
         *       ↘           ↙
         *  [request2]   [request5]
         *         ↘       ↙
         *             ↓
         *         [request3]
         * */
//        WorkContinuation then1 = WorkManager.getInstance().beginWith(request1).then(request2);
//        WorkContinuation then2 = WorkManager.getInstance().beginWith(request4).then(request5);
//        WorkContinuation.combine(then1,then2).then(request3).enqueue();

组合多任务的数据流

 在任务链中,我们可以把上一个任务的输出作为下一个任务的输入,场景如下

Android Jetpack之WorkManager使用详解_第4张图片

public class MyWorker extends Worker {
   
    private static final String TAG = "MyWorker";
    @NonNull
    @Override
    public Result doWork() {
       
        Data outputData = new Data.Builder().putString("MyWorker", "MyWorker-老张").build();
        setOutputData(outputData);
        return Result.SUCCESS;
    }
}

public class MainWorker2 extends Worker {

    @NonNull
    @Override
    public Result doWork() {
       
        Data outputData = new Data.Builder().putString("MainWorker2", "MainWorker2——老王")
              .build();
        setOutputData(outputData);

        return Result.SUCCESS;
    }
}


public class MainWorker3 extends Worker {
 
    private static final String TAG = "MainWorker3";
    @NonNull
    @Override
    public Result doWork() {
        Log.i("MainWorker3","work3执行了");

        Data inputData = getInputData();

        Log.i(TAG, "doWork: "+inputData.getKeyValueMap().size());

        Set> entries = inputData.getKeyValueMap().entrySet();
        for (Map.Entry mEntry : entries){

//注意 这里 的Value 是数组  数组 数组!!! 为什么 嘿嘿 请查看 OverwritingInputMerger 源码
Log.i(TAG, "doWork: "+mEntry.getKey() +"  /  "+mEntry.getValue().getClass().getName());

        }
    
        String data  = Arrays.toString(inputData.getStringArray("MyWorker"));
        data = data+" / "+Arrays.toString(inputData.getStringArray("MainWorker2"));
        Log.i(TAG, "doWork: "+data);
        return Result.SUCCESS;
    }
}


MainActivity{


  request1=new OneTimeWorkRequest.Builder(MyWorker.class).build();

  request2=new OneTimeWorkRequest.Builder(MainWorker2.class).build();

  request3=new OneTimeWorkRequest.Builder(MainWorker3.class)
               .setInputMerger(OverwritingInputMerger.class)
                .build();

  WorkContinuation then1 = WorkManager.getInstance().beginWith(request1) ;
  WorkContinuation then2 = WorkManager.getInstance().beginWith(request2) ;
  WorkContinuation.combine(then1,then2).then(request3).enqueue();

}

注意 在Work3中获取前任务的Value 是数组  数组 数组!!! 为什么 嘿嘿 请查看 OverwritingInputMerger 源码 没几行的

 

 

你可能感兴趣的:(Android,android,java)