WorkManager 多个任务顺序执行,携带数据,唯一队列功能
一、设置任务 Worker 任务执行顺序
对任务执行有顺序要求时:
- 多个任务单链式执行
执行顺序:
WorkManager.getInstance(mContext)
.beginWith(requestA)
.then(requestB)
.then(requestC)
.enqueue();
- 多个任务存在并行执行
执行顺序:
WorkManager.getInstance(mContext)
.beginWith(Arrays.asList(requestA1, requestA2, requestA3))
.then(requestB)
.then(Arrays.asList(requestC1, requestC2))
.enqueue();
- 多个任务并行后顺序执行
执行顺序:
WorkContinuation chain1 = WorkManager.getInstance(mContext)
.beginWith(requestA)
.then(requestB);
WorkContinuation chain2 = WorkManager.getInstance(mContext)
.beginWith(requestC)
.then(requestD);
WorkContinuation chain3 = WorkContinuation
.combine(Arrays.asList(chain1, chain2))
.then(requestE);
chain3.enqueue();
二、创建唯一的任务队列
对任务唯一性有要求时。场景举例:任务多,且每个任务的耗时都比较长时使用,可以防止正在进行又被重新执行;在类似数据同步过程中使用,可以防止被新的同步刷新。
当创建新的唯一工作序列时,如果已存在同名的未完成序列,需要指定 WorkManager 应执行什么操作:
WorkManager.getInstance(this).beginUniqueWork("UniqueName", ExistingWorkPolicy.KEEP, request)
.then(request2)
.then(request3)
.enqueue();
UniqueName:唯一队列名字,String 类型。
ExistingWorkPolicy:冲突时的操作,内部枚举类型
- ExistingWorkPolicy.REPLACE — 取消现有序列,并用新序列替换
- ExistingWorkPolicy.KEEP — 保留现有序列,并忽略新请求
- ExistingWorkPolicy.APPEND — 将新序列附加到现有序列后面,在现有序列的最后一个任务完成后,开始运行新系列的第一个任务
request:工作请求,OneTimeWorkRequest 类型。
三、将上个 Work 的结果作为下个 Work 的参数传入
work1:
public class MyWorker extends Worker {
private final String TAG = "MppCompatActivity";
public MyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
String result = "我是任务执行结果,这是String类型的结果。";
//任务执行结束返回该值
Data data = new Data.Builder()
.putString("result",result)
.build();
Log.d(TAG,"任务一执行结果:" + result);
return Result.success(data);
}
}
work2:
public class WorkTwo extends Worker {
private final String TAG = "MppCompatActivity";
public WorkTwo(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
String result = getInputData().getString("result");
Data data = new Data.Builder()
.putString("result", result)
.build();
Log.d(TAG, "任务二获取到的值:" + result);
return Result.success(data);
}
}
执行:
//任务1
OneTimeWorkRequest requestOne = new OneTimeWorkRequest.Builder(MyWorker.class)
.build();
OneTimeWorkRequest requestTwo = new OneTimeWorkRequest.Builder(WorkTwo.class).build();
//链式执行任务
workManager.beginWith(requestOne)
.then(requestTwo)
.enqueue();
//任务1
OneTimeWorkRequest requestOne = new OneTimeWorkRequest.Builder(MyWorker.class)
.build();
OneTimeWorkRequest requestTwo = new OneTimeWorkRequest.Builder(WorkTwo.class).build();
//链式执行任务
workManager.beginWith(requestOne)
.then(requestTwo)
.enqueue();
//对最终结果进行监听获取
workManager.getWorkInfoByIdLiveData(requestTwo.getId())
.observeForever(workInfo -> {
if(workInfo != null && workInfo.getState().isFinished()) {
Log.d(TAG, "所有任务执行结束,值为:" + workInfo.getOutputData().getString("result"));
}
});
Logcat 结果:
D/MppCompatActivity: 任务一执行结果:我是任务执行结果,这是String类型的结果。
D/MppCompatActivity: 任务二获取到的值:我是任务执行结果,这是String类型的结果。
D/MppCompatActivity: 所有任务执行结束,值为:我是任务执行结果,这是String类型的结果。
说明:获取结果时,使用 WorkManager.getInstance(myContext).getWorkInfoByIdLiveData(mathWork.getId()).observe(lifecycleOwner, info -> {}); 无法获取结果,改为 workManager.getWorkInfoByIdLiveData(requestTwo.getId()).observeForever(workInfo -> {});
原因:未深入查看,Log 显示为优先执行了 Observer.Onchange() 方法,但任务2的生命周期再次改变时,该回调未执行。
知识来源:官网及个人使用