WorkManager API可以轻松地让异步任务延迟执行以及何时运行它们,这些API可让我们创建任务并将其交给WorkManager,以便立即或在适当的时间运行。例如,应用程序可能需要不时从网络下载新资源,我们可以使用WorkManager API设置一个任务,然后选择适合它运行的环境(例如“仅在设备充电和联网时”),并在符合条件时将其交给 WorkManager 运行,即使该应用程序被强制退出或者设备重新启动,这个任务仍然可以保证运行
WorkManager适用于那些即使应用程序退出,系统也能够保证这个任务正常运行的场景,比如将应用程序数据上传到服务器。它不适用于应用进程内的后台工作,如果应用进程消失,就可以安全地终止,对于这种情况,需要选择ThreadPool、AsyncTask来实现。
Work的约束:
.setRequiredNetworkType(NetworkType.CONNECTED)//网络连接时执行
.setRequiresBatteryNotLow(true) //不在电量不足执行
.setRequiresCharging(true) //在充电时执行
.setRequiresStorageNotLow(true) //不在存储容量不足时执行
.setRequiresDeviceIdle(true) //在待机状态下执行 调用需要API级别最低为23
Work设置网络约束时的 各个值类型的作用
NetworkType.NOT_REQUIRED:对网络没有要求
NetworkType.CONNECTED:网络连接的时候执行
NetworkType.UNMETERED:不计费的网络比如WIFI下执行
NetworkType.NOT_ROAMING:非漫游网络状态
NetworkType.METERED:计费网络比如3G,4G下执行。
开始创建Work
package io.dcloud.H56580E2E.viewModelLiveData;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.google.gson.Gson;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.work.Data;
import androidx.work.Worker;
import io.dcloud.H56580E2E.R;
import io.dcloud.H56580E2E.info.ImageInfo;
import io.dcloud.H56580E2E.service.MainInterfaceService;
import io.dcloud.H56580E2E.util.BaseObserver;
import io.dcloud.H56580E2E.util.RetrofitHelper;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class DomeWork extends Worker {
// 服务请求接口
private MainInterfaceService main_interfaceService;
@NonNull
@Override
public WorkerResult doWork() {
/**
* WorkerResult.SUCCESS //成功
* WorkerResult.FAILURE //失败
* WorkerResult.RETRY //重试
*/
//接收传递进来的参数
String parame_str = this.getInputData().getString("workparame","");
Log.i("work","任务执行了"+parame_str);
main_interfaceService = RetrofitHelper.getInstance().create(MainInterfaceService.class);
//执行网络请求
getShufflingImageRequest();
//回传参数
String return_parame = "回传参数001";
Data data = new Data.Builder().putString("returnparame",return_parame).build();
setOutputData(data);
return WorkerResult.SUCCESS;
}
/**
* 网络请求,测试接口 使用的是 Rxjava2+RxAndroid+ReTrofit2 请求框架
*/
private void getShufflingImageRequest(){
main_interfaceService.getShufflingImage()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) //因为下面要发送通知所以必须在请求完成的时候把线程切换到 main 主线程中
.subscribe(new BaseObserver() {
@Override
protected void onFailure(Throwable e, boolean isNetWorkError) throws Exception {
//请求失败
Log.i("work","服务请求失败");
}
@Override
protected void onSuccees(ImageInfo imageInfo) throws Exception {
//请求成功
Gson gson = new Gson();
String data_str = gson.toJson(imageInfo);
Log.i("work","返回的数据"+data_str);
sendNotification();//发送通知
}
});
}
/**
* 发送一个通知
*/
private void sendNotification(){
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext(),"default");
mBuilder.setSmallIcon(R.mipmap.ic_launcher);//设置小图标
mBuilder.setContentTitle("我的work测试");//设置内容标题
mBuilder.setContentText("work执行完毕发送通知");//设置内容
mBuilder.setTicker("您有新的消息了");//通知弹出时状态栏的提示文本
mBuilder.setDefaults(Notification.DEFAULT_SOUND);//设置声音震动
mBuilder.setAutoCancel(true);//设置通知的点击行为,自动取消/跳转等
//创建一个意图
Intent intent = new Intent(getApplicationContext(),DomeActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),0,intent,PendingIntent.FLAG_CANCEL_CURRENT);
mBuilder.setContentIntent(pendingIntent);
//获取通知管理对象
NotificationManager mNotificaionManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
mNotificaionManager.notify(0,mBuilder.build());
}
}
在Activity中使用
package io.dcloud.H56580E2E.viewModelLiveData;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.work.Constraints;
import androidx.work.Data;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.PeriodicWorkRequest;
import androidx.work.State;
import androidx.work.WorkContinuation;
import androidx.work.WorkManager;
import androidx.work.WorkStatus;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.dcloud.H56580E2E.R;
import io.reactivex.functions.Consumer;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.jakewharton.rxbinding3.view.RxView;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class DomeActivity extends AppCompatActivity {
//Work请求
private OneTimeWorkRequest domeWork;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dome);
//Work执行
performWork();
}
/**
* 第一种.创建单个的 Work 任务
*/
private void performWork() {
//添加约束条件
/* Constraints myconstrain = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)//网络连接时执行
.setRequiresBatteryNotLow(true) //不在电量不足执行
.setRequiresCharging(true) //在充电时执行
.setRequiresStorageNotLow(true) //不在存储容量不足时执行
.setRequiresDeviceIdle(true) //在待机状态下执行 调用需要API级别最低为23
.build();*/
/**添加约束条件(网路连接时执行)
* 指定网络状态执行任务
* NetworkType.NOT_REQUIRED:对网络没有要求
* NetworkType.CONNECTED:网络连接的时候执行
* NetworkType.UNMETERED:不计费的网络比如WIFI下执行
* NetworkType.NOT_ROAMING:非漫游网络状态
* NetworkType.METERED:计费网络比如3G,4G下执行。
*/
Constraints mycoustrain = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED).build();
//传入参数(import androidx.work.Data)
Data data = new Data.Builder().putString("workparame", "workHelloWorld").build();
//构造work
domeWork = new OneTimeWorkRequest.Builder(DomeWork.class).setConstraints(mycoustrain).setInputData(data).build();
//放入执行队列
WorkManager.getInstance().enqueue(domeWork);
/**
* 任务执行状态的监听,可以获取到任务回传的参数
*/
WorkManager.getInstance().getStatusById(domeWork.getId())
.observe(this, new Observer() {
@Override
public void onChanged(WorkStatus workStatus) {
if (workStatus == null) {
return;
}
if (workStatus.getState() == State.ENQUEUED) {
//任务入列
Log.i("work", "任务入列");
}
if (workStatus.getState() == State.RUNNING) {
//任务正在执行
Log.i("work", "任务正在执行");
}
if (workStatus.getState().isFinished()) {
//任务执行完毕
Log.i("work", "任务执行完毕");
//接收回传的参数
Data outData = workStatus.getOutputData();
String out_parame = outData.getString("returnparame", "");
Toast.makeText(DomeActivity.this, "返回的参数" + out_parame, Toast.LENGTH_LONG).show();
}
}
});
}
/**
* 第二种.创建可以重复执行的任务(15m执行一次)
*/
public void cycleWork() {
//传入参数(import androidx.work.Data)
Data data = new Data.Builder().putString("workparame", "workHelloWorld").build();
//要创建循环任务,要使用PeriodicWorkRequest.Builder类创建一个PeriodicWorkRequest对象,然后将PeriodicWorkRequest以与OneTimeWorkRequest对象相同的方式入列
//任务15m循环(源码里面已经规定了最小时间间隔15分钟)
PeriodicWorkRequest.Builder invDomeWork = new PeriodicWorkRequest.Builder(DomeWork.class, 15, TimeUnit.MINUTES).setInputData(data);//每 15m 执行一次
PeriodicWorkRequest invWork = invDomeWork.build();
WorkManager.getInstance().enqueue(invWork);
//其它方法同第一种。。。
}
/**
* 第三种.创建链式任务
*/
public void chainWork() {
//添加约束条件(网路连接时执行)
Constraints mycoustrain = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED).build();
//传入参数(import androidx.work.Data)
Data data = new Data.Builder().putString("worktest", "workHelloWorld").build();
OneTimeWorkRequest oneA = new OneTimeWorkRequest.Builder(DomeWork.class).setConstraints(mycoustrain).setInputData(data).build();
OneTimeWorkRequest oneB = new OneTimeWorkRequest.Builder(DomeWork2.class).build();
OneTimeWorkRequest oneC = new OneTimeWorkRequest.Builder(DomeWork3.class).setConstraints(mycoustrain).setInputData(data).build();
OneTimeWorkRequest oneD = new OneTimeWorkRequest.Builder(DomeWork4.class).setConstraints(mycoustrain).setInputData(data).build();
OneTimeWorkRequest oneE = new OneTimeWorkRequest.Builder(DomeWork5.class).setConstraints(mycoustrain).setInputData(data).build();
/*******************************************************************以下三种运行时只能选择一种********************************************************************/
//1.行顺序为 oneA -> oneB -> oneC
//WorkManager根据每个任务的指定约束以请求的顺序运行任务,如果任何任务返回Worker.WorkerResult.FAILURE,则整个序列结束。
WorkManager.getInstance().beginWith(oneA)
.then(oneB)
.then(oneC).enqueue();
//2.执行顺序为 oneA 和 oneB 并行 oneA,oneB任务完成后执行 oneC
WorkManager.getInstance().beginWith(oneA,oneB)
.then(oneC).enqueue();
//3.创建复杂任务链 任务链chain1 与 chain2 并行 chain1和chain2完成后执行 oneE任务
// (在oneB之前运行oneA,它也在oneD之前运行oneC, oneB和oneD都完成后,WorkManager 运行oneE)
WorkContinuation chain1 = WorkManager.getInstance().beginWith(oneA).then(oneB);//创建 任务链1
WorkContinuation chain2 = WorkManager.getInstance().beginWith(oneC).then(oneD);//创建 任务链2
WorkContinuation chain3 = WorkContinuation.combine(chain1,chain2).then(oneE);//创建 任务链3
chain3.enqueue();
//其它方法同第一种。。。
}
/**
* 取消Work 任务
*/
private void cancelWork() {
//获取任务的Work ID
UUID comperssionWorkId = domeWork.getId();
WorkManager.getInstance().cancelWorkById(comperssionWorkId);
}
}