At a glance guide to AsyncTask in Android

android-market-leader-smartphone.png AsyncTask is an Android mechanism created to help handle long operations that need to report to the UI thread. To take advantage of this class, we need to create a new subclass of AsyncTask and implement its doInBackground(), onProgressUpdate(), and onPostExecute() methods. In other words, we are going to fill in the blanks for what to do in the background, what to do when there’s some progress, and what to do when the task completes.

Time consuming jobs such as big data processing, database or network accessing that run in UI thread may cause an ANR error (application not responding). The best solution to avoid ANR (Application not responding) error is using a worker thread running parallel with UI thread.

Before you start using the AsyncTask class, you'll need to understand the lifecycle compared to running an operation on the main thread.

android_asynctask.png

The first method that is called by an AsyncTask is onPreExecute(). This method runs on the UI thread and is meant for setting up any interface components that need to let the user know that something is happening.

After onPreExecute() has finished, doInBackground(T) is called. The generic parameter here is any information that you need to pass to the method for it to perform its task. For example, if you're writing a task that retrieves JSON from a URL, you would pass the URL to this method as a String. As an operation makes progress in doInBackground(), you can call onProgressUpdate(T) to update your UI (such as a progress bar on the screen). Here the generic is a value representing the progress, such as an Integer.

Once the doInBackground() method has completed, it can return an object that is passed into onPostExecute(T), such as a JSONObject that was downloaded from our initial URL. onPostExecute(T) runs on the UI thread.

The following are the four AsyncTask functions that can be used:

  • doInBackground – This is the main working function. If progress update is necessary, the publishProgress can be called, which will finally leads to the calling of onProgressUpdate. isCancelled() can be used to test the state of thread, so as to do the job properly.
  • onProgressUpdate – This method is invoked by calling publishProgress anytime from doInBackground call this method. UI update should only be done in this function.
  • onPreExecute – This is called before doInBackground.
  • onPostExecute – This is called after doInBackground. Result from doInBackground is passed to this method.

AsyncTask is a template class which takes three type arguments: the first is the type for argument of doInBackground; the second is the type for the argument of onProgressUpdate; the third is the type for the argument onPostExecute. These three functions each have an input argument of vargars type.

Bellow is simple example with AsyncTask. There are LinearLayout with a Button and a WebView. Click on Button will load page to WebView in AsyncTask. Very simple example but it give all "gotcha".

Here is activity_main.xml with LinearLayout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btnLoad"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="loadPage"
        android:text="Load page">
    </Button>

    <WebView
        android:id="@+id/wvPage"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

Following is MainActivity

public class MainActivity extends Activity {
    final Context context = this;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void loadPage(View view) {
        LoadPage task = new LoadPage();
        task.execute(new String[] {"http://proft.me"});
    }

    private class LoadPage extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... urls) {
            WebView wv = (WebView) findViewById(R.id.wvPage);
            wv.loadUrl(urls[0]);
            return null;
        }
        @Override
        protected void onPostExecute(String result) {
            Toast.makeText(MainActivity.this, "Page loaded", Toast.LENGTH_SHORT).show();
        }
    }
}

There is a issue when starting an AsyncTask and then rotating the screen. If you attempt to reference a Context item (such as a View or Activity) after the original Context has been destroyed, an Exception will be thrown. The easiest way around this is to call cancel(true) on your AsyncTask in your Activity or Fragment's onDestroy() method, and then validate that the task hasn't been canceled in onPostExecute(T).

Useful links

comments powered by Disqus