使用 WorkManager API 可以轻松地调度即使在应用退出或设备重启时仍应运行的可延迟异步任务。
可用于确保重要的后台任务一定会执行,比如上传,下载,同步服务器等操作
B站官方视频:https://www.bilibili.com/video/av56276889
WorkManager 旨在用于可延迟运行(即不需要立即运行)并且在应用退出或设备重启时必须能够可靠运行的任务。例如:
WorkManager 不适用于应用进程结束时能够安全终止的运行中后台工作,也不适用于需要立即执行的任务。请查看后台处理指南,了解哪种解决方案符合您的需求。
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;
}
}
执行结果如下
//构建限制条件 为了方便测试这里只加充电
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分钟再去判断限制条件执行
为什么说是10分钟呢,经过一番查找 找到源码如下
/*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();
在任务链中,我们可以把上一个任务的输出作为下一个任务的输入,场景如下
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 源码 没几行的