How to deal with asynchronous tasks in WorkManager

  • 2021-11-01 04:57:03
  • OfStack

Preface

WorkManager is a new component in Android Jetpack that is responsible for managing background tasks. I won't say much about the introduction of this component. It is everywhere on the Internet. Here, I share the method of handling asynchronous tasks in WorkManager.

As we know, in WorkManager, the way to handle tasks is to create a task class that inherits from Worker, implement the doWork () method, implement our own task in this method, and then return Result. success () or Result. failure () to indicate whether the task executed successfully or failed. Here, the tasks in the doWork () method should be synchronized, which is natural, since the doWork () method itself executes in child threads, so time-consuming operations can be synchronized in the doWork () method.

However, in some cases, we want to perform asynchronous tasks. In WorkManager, there are two better schemes to handle asynchronous tasks.

RxWorker

Many times we use RxJava to process data. Fortunately, we can use RxWorker to handle asynchronous tasks.


dependencies {
 ...
 implementation "android.arch.work:work-runtime:1.0.0-beta05"
 implementation "android.arch.work:work-rxjava2:1.0.0-beta05"
}

Then, change the class that previously integrated Work to inherit RxWorker, and then implement the createWork () method, with the following basic structure:


public class AsyncWorker extends RxWorker {

 public AsyncWorker(Context appContext, WorkerParameters workerParams) {
  super(appContext, workerParams);
 }

 @Override
 public Single<Result> createWork() {
  return remoteService.getMySingleResponse()
    .doOnSuccess(new Consumer() {
     @Override
     public void accept(Object object) throws Exception {
      //  Processing task 
     }
    })
    .map(new Function() {
     @Override
     public Object apply(Object object) throws Exception {
      return Result.success();
     }
    })
    .onErrorReturn(new Function() {
     @Override
     public Object apply(Object object) throws Exception {
      return Result.failure();
     }
    });
 }
}

It's simple, isn't it? One thing to note is that the createWork () method is executed in the main thread by default, and it will automatically cancel if the task does not end in 10 minutes.

ListenableWorker

When we look at the source code of RxWorker, we can find that it inherits ListenableWorker class, but Worker is also realized by inheriting ListenableWorker. Therefore, we can achieve the same function by customizing ListenableWorker.

Look at the source code of Worker under 1, which is very simple:


public abstract class Worker extends ListenableWorker {
 SettableFuture<Result> mFuture;
 public Worker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
  super(context, workerParams);
 }

 @WorkerThread
 public abstract @NonNull Result doWork();
 @Override
 public final @NonNull ListenableFuture<Result> startWork() {
  mFuture = SettableFuture.create();
  getBackgroundExecutor().execute(new Runnable() {
   @Override
   public void run() {
    Result result = doWork();
    mFuture.set(result);
   }
  });
  return mFuture;
 }
}

Can use the main SettableFuture this class, in startWork () first created SettableFuture object, and then opened a sub-thread, in the sub-thread inside the execution of doWork () method, finished using mFuture. set () method to return Result.

Therefore, we can also imitate the writing of Worker class to realize our own asynchronous processing. Simply the template code is as follows:


public class AsyncWorker extends ListenableWorker {
 private SettableFuture<Result> mFuture;
 public AsyncWorker(Context appContext,WorkerParameters workerParams) {
  super(appContext, workerParams);
 }

 @Override
 public ListenableFuture<Result> startWork() {
  mFuture = SettableFuture.create();
  doSomeAsyncWork(new AsyncListener() {
   @Override
   public void success() {
    mFuture.set(Result.success());
   }
   
   @Override
   public void fail() {
    mFuture.set(Result.failure());
   }
  });
  return mFuture;
 }
}

Summarize


Related articles: