WorkManager是用于后台执行任务的工具,相比于Service、JobSchedule等,它拥有很低的能耗,但是它不是立即执行任务的,对于一些不需要及时完成的任务,使用WorkManager是一个很好的选择
WorkManager内部使用了数据库,所以能保证任务一定会执行。WorkManager的兼容性也很好,最低支持api14,api23以前,WorkManager内部是使用了JobSchedule,23以后使用的是AlarmManager+BroadCastReceiver
使用WorkManager需要添加gradle依赖:
implementation 'androidx.work:work-runtime:2.5.0'
1.使用WorkManager
定义Work类,继承Worker,doWork方法需要返回一个Result的结果,有成功、重试、失败:
package com.aruba.workmanager;import android.content.Context;
import android.util.Log;import androidx.annotation.NonNull;
import androidx.work.Worker;
import androidx.work.WorkerParameters;/*** Created by aruba on 2021/9/15.*/
public class MyWork extends Worker {private static final String TAG = MyWork.class.getSimpleName();public MyWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {super(context, workerParams);}@NonNull@Overridepublic Result doWork() {Log.i(TAG,"doWork");return Result.success();}
}
在适当的地方,将任务入队:
//设置条件Constraints constraints = new Constraints.Builder()//NetworkType.CONNECTED:需要有网络//NetworkType.NOT_REQUIRED:不需要网络//NetworkType.NOT_ROAMING:非漫游网络//NetworkType.METERED:计费网络下执行(流量)//NetworkType.UNMETERED:不计费网络(wifi).setRequiredNetworkType(NetworkType.NOT_REQUIRED)
// .setRequiresBatteryNotLow(true)//不在低电量
// .setRequiresCharging(true)//充电时执行
// .setRequiresStorageNotLow(true)//不在低存储空间
// .setRequiresDeviceIdle(true)//不在待机 api23.build();//配置任务OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(MyWork.class).setConstraints(constraints)//设置延迟.setInitialDelay(5, TimeUnit.SECONDS).build();//任务入队WorkManager.getInstance(this).enqueue(workRequest);
2.指数退避策略
我们也可以为任务配置指数退避策略,当任务需要retry时,它会根据给定的退避时间指数增长,列如:退避时间为2,重试的时间间隔为:2,4,8...
//配置任务OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(MyWork.class).setConstraints(constraints)//设置延迟.setInitialDelay(5, TimeUnit.SECONDS)//指数退避策略.setBackoffCriteria(BackoffPolicy.LINEAR,2,TimeUnit.SECONDS).build();
3.为任务配置TAG
//配置任务OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(MyWork.class).setConstraints(constraints)//设置延迟.setInitialDelay(5, TimeUnit.SECONDS)//指数退避策略.setBackoffCriteria(BackoffPolicy.LINEAR,2,TimeUnit.SECONDS)//设置tag.addTag("work1").build();
4.监听任务状态
使用workManager对任务状态进行监听
//添加任务监听workManager.getWorkInfoByIdLiveData(workRequest.getId()).observe(this, new Observer<WorkInfo>() {@Overridepublic void onChanged(WorkInfo workInfo) {Log.i("WorkInfo", workInfo.toString());}});
5.取消任务
//取消任务workManager.cancelWorkById(workRequest.getId());
6.参数传递
参数传递分成两方面,一个是创建任务时传入参数,一个是执行任务时传递参数
使用Data在创建任务时传入参数:
//传入参数Data data = new Data.Builder().putString("createTask", "createTask").build();//配置任务OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(MyWork.class).setConstraints(constraints)//设置延迟.setInitialDelay(5, TimeUnit.SECONDS)//指数退避策略.setBackoffCriteria(BackoffPolicy.LINEAR, 2, TimeUnit.SECONDS)//设置tag.addTag("work1")//传入参数.setInputData(data).build();
在我们自定义的Work中,doWork方法内可以获取到创建时传递的参数,并且传递新的参数
@NonNull@Overridepublic Result doWork() {Log.i(TAG,"doWork");//获取参数String createTask = getInputData().getString("createTask");Log.i(TAG,"createTask");//传递新参数Data data = new Data.Builder().putString("doWork", "doWork complete").build();return Result.success(data);}
可以在监听任务状态时,获取完成任务的参数:
//添加任务监听workManager.getWorkInfoByIdLiveData(workRequest.getId()).observe(this, new Observer<WorkInfo>() {@Overridepublic void onChanged(WorkInfo workInfo) {Log.i("WorkInfo", workInfo.toString());if (workInfo != null && workInfo.getState() == WorkInfo.State.SUCCEEDED) {String doWork = workInfo.getOutputData().getString("doWork");Log.i("WorkInfo", doWork);}}});
7.周期性任务
使用PeriodicWorkRequest对象,并且指定的时间不能低于15分钟
//周期性任务if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(MyWork.class, Duration.ofMinutes(15)).build();}
8.任务链与任务组合
任务也是可以链式执行的:
OneTimeWorkRequest aWork = new OneTimeWorkRequest.Builder(AWork.class).build();OneTimeWorkRequest bWork = new OneTimeWorkRequest.Builder(BWork.class).build();//先执行A再执行BworkManager.beginWith(aWork).then(bWork).enqueue();
任务组合,使用WorkContinuation的combine方法来组合WorkContinuation集合执行,可以使用then方法指定延后执行的任务:
OneTimeWorkRequest aWork = new OneTimeWorkRequest.Builder(AWork.class).build();OneTimeWorkRequest bWork = new OneTimeWorkRequest.Builder(BWork.class).build();OneTimeWorkRequest cWork = new OneTimeWorkRequest.Builder(CWork.class).build();OneTimeWorkRequest dWork = new OneTimeWorkRequest.Builder(DWork.class).build();OneTimeWorkRequest eWork = new OneTimeWorkRequest.Builder(EWork.class).build();//先A再BWorkContinuation workContinuation1 = workManager.beginWith(aWork).then(bWork);//先C再DWorkContinuation workContinuation2 = workManager.beginWith(cWork).then(dWork);List<WorkContinuation> workContinuations = new ArrayList<>();workContinuations.add(workContinuation1);workContinuations.add(workContinuation2);//最后执行EWorkContinuation.combine(workContinuations).then(eWork).enqueue();