A, WorkManager Introduction
WorkManager is a component Jetpack component library, and is responsible for managing background tasks .
WorkManager API allows you to more easily manage some background task, even if your application is to exit or reboot the state .
WorkManager apply to delay the execution of tasks, need not be performed immediately, and can reliably execute even exit the application or the device is restarted . E.g:
- Send to a back-end service log analysis
- Regular data synchronization with the server application
WorkManager does not apply to those background tasks disappear when the application process can safely be terminated .
WorkManager and traditional background tasks Service difference:
- WorkManager will not disappear because the application process is terminated, even if the device is restarted. The Service is not.
- Service is more suitable for background tasks in the application.
- WorkManager delay can be set to perform, need not be performed immediately, that is, we often say that the timing of the task.
Two, WorkManager core classes
Let's take a look at a few categories related to WorkManager:
-
Worker
executive tasks , is a abstract class , inherit it needs to achieve the tasks to be performed. -
WorkRequest
environment specified execution, the order of execution which Woker specify that the mission, and so on.
To use its subclasses OneTimeWorkRequest or PeriodicWorkRequest . -
WorkManager
management task requests and the task queue , initiated WorkRequest will enter its task queue. -
WorkStatus
includes information task status and tasks to LiveData provided to the observer form.
Three, WorkManager use
1. Import dependencies
implementation "android.arch.work:work-runtime:1.0.1"
2. Use Worker defined task
public class UploadLogWorker extends Worker {
private static final String TAG = "UploadLogWorker";
public UploadLogWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
/**
* 处理耗时任务
* @return Result
*/
@NonNull
@Override
public Result doWork() {
Log.d(TAG, "doWork()");
return Result.success();
}
}
the doWork () method returns the value of three types:
- Implementation of successful return Result.success ()
- Fails to return Result.failure ()
- Need to re-execute return Result.retry ()
3. Use WorkRequest configuration tasks
By WorkRequest configure our task when to run and how to run .
(1) by Constraints trigger condition setup tasks
For example, we can set in the device is charging, the network is connected and the battery is fully charged state, before starting the task we set.
Constraints constraints = new Constraints.Builder()
.setRequiresCharging(true)
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build();
(2) to set the Constraints WorkRequest
WorkRequest is an abstract class, which has two implementations:
- OneTimeWorkRequest: a one-time task
- PeriodicWorkRequest: periodic tasks
WorkRequest can also set the delay to perform the task . Assuming you do not set trigger conditions, or when you set a trigger condition to perform in line with the requirements of the system, this time, the system may perform the task immediately, but if you want to be able to delay the execution, you can setInitialDelay () method, deferred tasks execution.
WorkRequest can also set the exponential backoff strategy . If the execution Worker threads appeared abnormal, such as server goes down, then you might want some time, retry the task. Then you can return Result.retry in Worker's doWork () method (), the system will default exponential backoff strategy to help you retry the task, you can also setBackoffCriteria () method, custom exponential backoff strategy.
OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadLogWorker.class)
.setConstraints(constraints)//设置触发条件
.setInitialDelay(10, TimeUnit.SECONDS) //符合触发条件后,延迟10秒执行
.setBackoffCriteria(BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS)//设置指数退避算法
.addTag("UploadTag") //设置Tag
.build();
(3) by WorkManager to perform tasks
WorkManager.getInstance().enqueue(uploadWorkRequest);
Cancel tasks:
And observation tasks Similarly, we can also cancel a task according to Id or Tag, or cancel all tasks.
WorkManager.getInstance(MainActivity.this).cancelAllWork();
Four, WorkManager expand
1. The status of observer mission
After the mission submitted to the system, by WorkInfo state learned tasks, WorkInfo contains the task id, tag, and outputData Worker object passed over, and the current status of the task.
There are three ways you can get WorkInfo objects :
- WorkManager.getWorkInfosByTag()
- WorkManager.getWorkInfoById()
- WorkManager.getWorkInfosForUniqueWork()
If you want to know the real-time status of the task. These three methods there is a corresponding LiveData method.
- WorkManager.getWorkInfosByTagLiveData()
- WorkManager.getWorkInfoByIdLiveData()
- WorkManager.getWorkInfosForUniqueWorkLiveData()
By the time LiveData, we can change occurred in the task state notified.
WorkManager.getInstance(this).getWorkInfoByIdLiveData(uploadWorkRequest.getId()).observe(MainActivity.this, new Observer<WorkInfo>()
{
@Override
public void onChanged(WorkInfo workInfo)
{
Log.d("onChanged()->", "workInfo:"+workInfo);
}
});
2. Data transfer
Worker data between WorkManager and transferred through Data to accomplish the object.
WorkManager by setInputData () to pass data to Worker method.
Data inputData = new Data.Builder().putString("input_data", "Hello World!").build();
OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadLogWorker.class)
.setInputData(inputData)
.build();
Worker receiving data, and the task execution is completed, the data is transmitted to WorkManager.
@Override
public Result doWork()
{
//接收外面传递进来的数据
String inputData = getInputData().getString("input_data");
// 任务执行完成后返回数据
Data outputData = new Data.Builder().putString("output_data", "Task Success!").build();
return Result.success(outputData);
}
WorkManager by LiveData of WorkInfo.getOutputData () , obtained from the data transfer over the Worker.
WorkManager.getInstance(this).getWorkInfoByIdLiveData(uploadWorkRequest.getId()).observe(MainActivity.this, new Observer<WorkInfo>()
{
@Override
public void onChanged(WorkInfo workInfo)
{
if (workInfo != null && workInfo.getState() == WorkInfo.State.SUCCEEDED)
{
String outputData = workInfo.getOutputData().getString("output_data");
}
}
});
Note: the Data transfer can only be used for some small basic types of data, and the data can not be over 10kb.
3. periodic task
Periodic task PeriodicWorkRequest regularly performed in a set time. Compared with OneTimeWorkRequest, there is not much difference between the two to use.
Note that: the time interval for periodic tasks not be less than 15 minutes .
PeriodicWorkRequest uploadWorkRequest = new PeriodicWorkRequest.Builder(UploadLogWorker.class, 15, TimeUnit.MINUTES)
.setConstraints(constraints)
.addTag(TAG)
.build();
4. The task chain
If you have a series of tasks to be performed sequentially, you can use WorkManager.beginWith (). Then (). Then () ... enqueue () method. For example: Before we upload data, you need to compress the data.
WorkManager.getInstance(this).beginWith(compressWorkRequest).then(uploadWorkRequest).enqueue();
Suppose there are more complex task chain, you can also consider using WorkContinuation.combine () method, the combined task chain.
WorkContinuation workContinuation1 = WorkManager.getInstance(this).beginWith(WorkRequestA).then(WorkRequestB);
WorkContinuation workContinuation2 = WorkManager.getInstance(this).beginWith(WorkRequestC).then(WorkRequestD);
List<WorkContinuation> taskList = new ArrayList<>();
taskList.add(workContinuation1);
taskList.add(workContinuation2);
WorkContinuation.combine(taskList).then(WorkRequestE).enqueue();