In Android like in others platforms, it can be useful to use asynchronous tasks to process long operations like download a file or consume a web service. In Java, you know that the entry point is the Thread class. Android using a part of Java API, you can also use Thread class but it’s to you to manage synchronization with the main thread for example and you have no possibility to cancel a thread.

A more easy way is provided by Android SDK : the AsyncTask class. The AsyncTask class encapsulates the creation of a background process and the synchronization with the main thread. It also supports reporting progress of the running tasks.

To create an Asynchronous Task, you must subclass the AsyncTask class that uses generics and varargs.

Started with its execute() method, an AsyncTask lets developers to override following methods :

  • onPreExecute() that is called in the main thread
  • doInBackground() that is called in an independant thread and where you must call the long processing operations
  • onPostExecute() that is called when the AsyncTask is ended and that lets you to get result if needed.
  • onProgressUpdate() that is called in the main thread when you call the method publishProgress() in doInBackground()

The main advantage here is that is synchronization is delegated to Android OS. Thread pooling is also managed directly by AsyncTask and it’s transparent for developers. Main disadvantage of the AsyncTask is the fact that it does not handle configuration changes automatically. It’s your job to take this in account and to manage it.

Theory explained, we can start the practice with a sample code :


// First generic here is type for entered parameter of the AsyncTask, second is type for
// progress results published and last type is the result of the process.
// Here it's a Result class
public class LongOperation extends AsyncTask<String, Integer, Result>{

  @Override
  protected void onPreExecute() {
    super.onPreExecute();
    // called in main thread, you can use to display progress
    // dialog to users
  }

  @Override
  protected void onProgressUpdate(Integer... values){
    super.onProgressUpdate(values);
    // called in main thread, if you use a progress bar you can
    // update the value
    mProgressBar.setProgress(values[0]);
  }

  @Override
  protected Result doInBackground(String... arg) {
    // Called in a separate thread
    // Here you can get String arguments entered when you
    // call execute() method of the AsyncTask

    int progress = 0;
    Result result = null;

    // long process
    for (...) {
      // ...
      publishProgress(progress);
    }

    // here we get result object setted

    return result;
  }

  @Override
  protected void onPostExecute(Result result) {
    // Called in main thread, here we get the result
  }
}

Your AsyncTask defined, you must start its execution. To achieve that, you must use the following code :


if (Build.VERSION.SDK_INT >= 11) {
   myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, param1, param2, ...);
} else {
   myTask.execute(param1, param2, ...);
}

If you plan to targets SDK prior version 11, you must use a test. Indeed, before SDK version 11, asynchronous tasks were automatically launched in parallel. Now, you must specify that you want use a thread pool executor.

 

Future tutorials will show you how to use directly Threads in your applications and how to send messages to main thread thanks to Handler class.