Jetpack:WorkManager任务调度与管理


WorkManager是什么

  2018年Google I/O大会上推出了一个新的包Jetpack,其中包含了几个类WorkManager、Paging、Navigation 以及 Slices.其中WorkManager就是用来替换之前的Jobschedule,它可以管理一个任务,使任务在特定条件下执行,可以单次和循环执行.还可以设置延时执行等一系列功能.

WorkManager优点

  • 支持所有android版本
  • 易于取消:可以根据Id直接取消任务
  • 易于调度:可以按顺序执行任务,可设置约束条件,可以延时执行
  • 易于查询:可以订阅到任务的执行状态

WorkManager使用依赖

implementation "android.arch.work:work-firebase:1.0.0-alpha08"
androidTestImplementation "android.arch.work:work-testing:1.0.0-alpha08"

注意:alpha09版本将Worker类定义为弃用类,暂时没有找到替代类


WorkManager中重要的类

  • Constraints(约束条件):可以为worker设置特定的运行条件,如在特定网络下执行,是否在电量不足时执行,是否在充电时执行,是否在存储容量不足时执行,是否在待机状态下执行.
  • Data(数据):通过设置setInputData将数据传入worker中,通过setOutputData将数据传出(及返回值)
  • OneTimeWorkRequest(单次工作请求):创建一个只能单次执行的请求,可以延时执行
  • PeriodicWorkRequest(多次工作请求):创建一个多次执行的请求,可以延时执行
  • WorkManager(工作管理器):管理任务执行与停止,任务执行先后顺序
  • WorkContinuation(任务链):可以同时执行多条任务链
  • WorkStatus(任务状态):任务状态,用于订阅任务,观察任务状态的改变,获取返回值

WorkManager使用实例

(1)创建worker类

public class TestWorker extends Worker {
    private String TAG = "test";
    @NonNull
    @Override
    public Result doWork() {
        String data = getInputData().getString("workerData");
        Log.d(TAG,"doWork:"+data);
        return Result.SUCCESS;
    }
}

(2)通过WorkManager启动Worker

import android.annotation.TargetApi;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.util.concurrent.TimeUnit;
import androidx.work.Constraints;
import androidx.work.Data;
import androidx.work.OneTimeWorkRequest;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;

public class MainActivity extends AppCompatActivity {

    @TargetApi(Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //约束条件      setRequiredNetworkType在特定网络下执行
        Constraints mConstraints = new Constraints.Builder()
                .setRequiresBatteryNotLow(true)//不在电量不足时执行
                .setRequiresCharging(true)//在充电时执行
                .setRequiresStorageNotLow(true)//不在存储容量不足时执行
                .setRequiresDeviceIdle(true)//在待机状态执行
                .build();
        //传入参数
        Data data = new Data.Builder().putString("workerData","helloWorld").build();
        //构造只执行一次的worker
        OneTimeWorkRequest testWorker = new OneTimeWorkRequest.Builder(TestWorker.class)
                .setInputData(data)
                .setInitialDelay(5,TimeUnit.SECONDS)  //延时执行worker
                .setConstraints(mConstraints).build();
        //重复执行的worker
//        PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(TestWorker.class,15,
//                TimeUnit.SECONDS).setConstraints(mConstraints)
//                .setInputData(data).build();
        //放入任务队列
        WorkManager.getInstance().enqueue(testWorker);
        //安顺序执行worker
//        WorkManager.getInstance().beginWith(testWorker).then(testWorker).enqueue();
    }
}

(3)按顺序执行Worker

WorkManager.getInstance().beginWith(A).then(B).enqueue(); //按顺序逐个执行
WorkManager.getInstance().beginWith(A,B).then(C).enqueue();//A,B同时执行,然后执行C

(4)按任务链执行
  任务链可以设置多个任务线不同的执行顺序

//同时执行任务链1和2,执行完成后执行E
WorkContinuation workContinuation1 = WorkManager.getInstance().beginWith(A).then(B);
WorkContinuation workContinuation2 = WorkManager.getInstance().beginWith(C).then(D);
WorkContinuation workContinuation3 = WorkContinuation.combine(workContinuation1,workContinuation2).then(E);
workContinuation3.enqueue();

(5)为Worker设置返回数据
  通过 setOutputData()设置返回结果,我们需要通过WorkManager来设置订阅,根据任务的id来订阅任务的状态改变,就可以获取到返回值.

public class TestWorker extends Worker {
    private String TAG = "test";
    @NonNull
    @Override
    public Result doWork() {
        String data = getInputData().getString("workerData");
        Log.d(TAG,"doWork:"+data);
        Data responseData = new Data.Builder().putString("response","ok").build();
        setOutputData(responseData);

        return Result.SUCCESS;
    }
}

(6)通过WorkManager订阅返回数据
  通过Id来订阅任务的状态改变,可以判断状态类型,只对某些状态进行处理,状态类型包括:ENQUEUED(开始执行),RUNNING(正在运行),SUCCEEDED(任务已经完成),FAILED(任务已经完成,但是任务失败),BLOCKED(任务被阻塞,还未完成),CANCELLED(任务被取消).

	 //订阅返回数据
        WorkManager.getInstance()
                .getStatusById(testWorker.getId())
                .observeForever(new Observer<WorkStatus>() {
                    @Override
                    public void onChanged(@Nullable WorkStatus workStatus) {
                        Data response = workStatus.getOutputData();
                        Log.d("test","response:"+response.getString("response"));
                    }
                });

(7)取消Worker

	WorkManager.getInstance().cancelWorkById(testWorker.getId());

beginUniqueWork启动任务

  通过这个方法启动woker时需要制定一个workName,当任务队列中已经存在该任务时,你可以制定是否要替换,保持或者追加新任务.通过ExistingWorkPolicy设置以哪种方式处理相同name的任务

(1)调用方法

/** @param uniqueWorkName  一个任务名称
 * @param existingPeriodicWorkPolicy 处理同名任务的方式
 */ @param periodicWork 可以传入多个单次执行的任务
 public final @NonNull WorkContinuation beginUniqueWork(
            @NonNull String uniqueWorkName,
            @NonNull ExistingWorkPolicy existingWorkPolicy,
            @NonNull OneTimeWorkRequest... work) {
        return beginUniqueWork(uniqueWorkName, existingWorkPolicy, Arrays.asList(work));
    }
/** @param uniqueWorkName  一个任务名称
  * @param existingPeriodicWorkPolicy 处理同名任务的方式
  */ @param work 多个单次执行的任务列表
   public abstract @NonNull WorkContinuation beginUniqueWork(
            @NonNull String uniqueWorkName,
            @NonNull ExistingWorkPolicy existingWorkPolicy,
            @NonNull List<OneTimeWorkRequest> work);

(2)ExistingWorkPolicy的类型

  • ExistingWorkPolicy.REPLACE:将已有的任务取消且删除掉,替换成新的任务
  • ExistingWorkPolicy.KEEP:什么也不做,继续执行之前的任务
  • ExistingWorkPolicy.APPEND:追加一个新的任务

源码地址

WorkManagerDemo


你可能感兴趣的:(Android)