Android Jetpack (八) WorkManager

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();
Published 67 original articles · won praise 69 · views 20000 +

Guess you like

Origin blog.csdn.net/qq_34519487/article/details/104340128