Home » AsyncTask deprecated alternative Android

AsyncTask deprecated alternative Android

  • by
AsyncTask deprecated alternative Android

1. Overview

In this article, we will learn the alternative solutions to the deprecated AsyncTask in Android using Java.

An AsyncTask is an asynchronous task that runs on a background thread and publishes the result on the UI thread.

This API is deprecated in API level 30 and recommended using

  1. java.util.concurrent
  2. Kotlin concurrency utilities.

Here, we will use the java.util.concurrent.

2. Why AsyncTask is deprecated in Android

AsyncTask could cause

  1. Context leaks
  2. Missed callbacks
  3. Crashes on configuration changes
  4. Inconsistent behavior on different versions of the platform
  5. Swallows exceptions from doInBackground. Error hiding or Swallowing exception is the practice of catching an error or exception, and then continuing without logging, processing, or reporting the error to other parts of the app. Swallowing exceptions are considered bad practice as information about the error is lost and makes it very hard to track down the root cause of the problems.
  6. Provide little utility when compared with Executors directly.

AsyncTask is a helper class around Thread and Handler and does not have any components that can manage threads efficiently.

You can use the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask.

3. AsyncTask deprecated alternative Android - Java

Here, we are using the Executor class as an alternative to the deprecated AsyncTask.

First, create an instance of the executor by using any of the factory methods:

private final Executor executor = Executors.newSingleThreadExecutor();

A Handler gives you a mechanism to push tasks into the UI thread queue from any other threads thus allowing other threads to communicate with the UI thread. Looper includes a helper function, getMainLooper(), which retrieves the Looper of the main thread. To learn more about Handler, see this article.

Now, let’s retrieve the handler of the UI thread to publish error or results back from the asynchronous task.

private final Handler handler = new Handler(Looper.getMainLooper());

You can use execute method of the Executor class to execute any task asynchronously and publish error or result back to the UI thread by using the handler.

executor.execute(() -> {
            final R result;
            try {
                // perform task asynchronously
                // you can also execute runnable or callable
                handler.post(() -> {
                    // update the result to the UI thread
                    // or any operation you want to perform on UI thread. It is similar to onPostExecute() of AsyncTask
                });
            } catch (Exception e) {
                e.printStackTrace();
                handler.post(() -> {
                    // update error to UI thread or handle
                });
            }
        });

You can use the above code in your app to run tasks asynchronously replacing the AsyncTask. However, you can also use the below class that contains the above Executor logic in a reusable way that would make the code cleaner:

package com.tedblob.rxjava;
import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class ExecutorRunner {
    // Executor instance
    private final Executor executor = Executors.newSingleThreadExecutor();
    // UI thread handler
    private final Handler handler = new Handler(Looper.getMainLooper());
    // callback interface to communicate result or error
    public interface Callback<R> {
        void onComplete(R result);
        void onError(Exception e);
    }
    public <R> void execute(Callable<R> callable, Callback<R> callback) {
        // Executor's execute method to execute the task asynchronously
        executor.execute(() -> {
            final R result;
            try {
                result = callable.call();
                handler.post(() -> {
                    callback.onComplete(result);
                });
            } catch (Exception e) {
                e.printStackTrace();
                handler.post(() -> {
                    callback.onError(e);
                });
            }
        });
    }
}

You can also execute Runnable or Callable using the Executor. We will execute the below Callable task by using the execute method of the Executor interface.

package com.tedblob.rxjava;
import java.util.concurrent.Callable;
class SampleCallable implements Callable<String> {
    private final String input;
    public SampleCallable(String input) {
        this.input = input;
    }
    @Override
    public String call() {
        return input;
    }
}

You can create an instance of the above ExecutorRunner and pass the above callable task to run asynchronously.

 executorRunner.execute(new SampleCallable("Input for Sample Callable"), new ExecutorRunner.Callback<String>() {
            @Override
            public void onComplete(String result) {
                // Result returned from the asynchronous task 
            }
            @Override
            public void onError(Exception e) {
                  // any error while running the task asynchronously 
            }
        });

4. Conclusion

To sum up, we have learned the alternative to deprecated AsyncTask in Android (Java).

Leave a Reply

Your email address will not be published.