Android App Development:Threading part 2: Async Tasks

In the previous post we saw one way to deal with threads in Android, which is by using Handlers. In this post we’ll see how to use another technique which is using AsyncTask class.

AsyncTask is an abstract class that provides several methods managing the interaction between the UI thread and the background thread. it’s implementation is by creating a sub class that extends AsyncTask and implementing the different protected methods it provides.

Let’s demonstrate how to user AsyncTask by creating a simple activity that has two buttons and a progress bar:

<?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/btn"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="Show Progress"
  ></Button>
  <ProgressBar
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:id="@+id/progress"
  style="?android:attr/progressBarStyleHorizontal"
  ></ProgressBar>
  <Button
  android:id="@+id/btnCancel"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="Cancel"
  ></Button>
</LinearLayout>

Here we have two buttons: one to start progress and the other to stop it.

Creating the AsyncTask sub class:

The first step in implementing AsyncTask is to create a sub class like this:

class ProgressTask extends AsyncTask<Params, Progress, Result>{
}

The AsyncTask declaration has three Varargs parameters which are:

  1. Params: parameter info passed to be used by the AsyncTask.
  2. Progress: the type of progress that the task accomplishes.
  3. The result returned after the AsyncTask finishes.

These parameters are of type Varargs which provide the flexibility to pass dynamic sized arrays as parameters.

In our example our class will be like this:

class ProgressTask extends AsyncTask<Integer, Integer, Void>{
}

The parameter and the progress are of type Integer and the result is Void as our tasks does not return anthing (returns null).

The second step is overriding the protected methods defined by the AsyncTask class that handle the execution life cycle of the AsyncTask.

We have five methods to implement which are:

  1. onPreExecute: the first method called in the AsyncTask, called on the UI thread.
  2. doInBackground: the method that executes the time consuming tasks and publish the task progress, executed in background thread.
  3. onProgressUpdate: method that updates the progress of the AsyncTask, run on the UI thread.
  4. onPostExecute: the final method that gets called after doInBackground finishes, here we can update the UI with the results of the AsyncTask.
  5. onCancelled: gets called if the AsyncTask.cancel() methods is called, terminating the execution of the AsyncTask.

Starting the AsyncTask:

To start the AsyncTask we create an instance of it, then call the execute() method passing the initial parameters like this:

ProgressTask task=new ProgressTask();
// start progress bar with initial progress 10
task.execute(10);

Implementing the AsyncTask:

class ProgressTask extends AsyncTask<Integer, Integer, Void>{

		@Override
		protected void onPreExecute() {
			// initialize the progress bar
			// set maximum progress to 100.
			progress.setMax(100);

		}

		@Override
		protected void onCancelled() {
			// stop the progress
			progress.setMax(0);

		}

		@Override
		protected Void doInBackground(Integer... params) {
			// get the initial starting value
			int start=params[0];
			// increment the progress
			for(int i=start;i<=100;i+=5){
				try {
					boolean cancelled=isCancelled();
					//if async task is not cancelled, update the progress
					if(!cancelled){
						publishProgress(i);
						SystemClock.sleep(1000);

					}

				} catch (Exception e) {
					Log.e("Error", e.toString());
				}

			}
			return null;
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			// increment progress bar by progress value
			progress.setProgress(values[0]);

		}

		@Override
		protected void onPostExecute(Void result) {
			// async task finished
			Log.v("Progress", "Finished");
		}

	}

Here are the steps:

  1. onPreExecute() method first gets called initializing the maximum value of the progress bar.
  2. doInBackground(Integer… params) methods gets called by obtaining the initial start value of the progress bar then incrementing the value of the progress bar every second and publishing the progress as long as the async task is not cancelled.
  3. onProgressUpdate(Integer… values) method is called each time progress is published from doInBackground, thus incrementing the progress bar.
  4. onPostExecute(Void result) is called after doInBackground finished execution.
  5. void onCancelled() is called if task.cancel(true) is called from the UI thread. it may interrupt the execution preventing onPostExecute from being executed.

The onClick handler of our buttons is like this:

@Override
	public void onClick(View v) {
		ProgressTask task=new ProgressTask();
		switch(v.getId()){
		case R.id.btn:
			task.execute(10);
			break;
		case R.id.btnCancel:
			task.cancel(true);		
			break;
		}

	}

The Difference between Handler and AsyncTask:

After we saw both Handlers and AsyncTasks a question may evolve: what’s the difference between the two and when to use one of them over the other ?

The Handler is associated with the application’s main thread. it handles and schedules messages and runnables sent from background threads to the app main thread.

AsyncTask provides a simple method to handle background threads in order to update the UI without blocking it by time consuming operations.

The answer is that both can be used to update the UI from background threads, the difference would be in your execution scenario. You may consider using handler it you want to post delayed messages or send messages to the MessageQueue in a specific order.

You may consider using AsyncTask if you want to exchange parameters (thus updating UI) between the app main thread and background thread in an easy convinient way.

We hope you fund this tutorial on Android AsyncTask helpful, stay tuned for another tutorial next week.


10 Responses to “Android App Development:Threading part 2: Async Tasks”

  1. Søren Hansen 15. Jul, 2011 at 8:53 am #

    Great article!
    Could you attach the project? Seems stuff are missing.

  2. pawan 30. Aug, 2011 at 8:46 am #

    awesome … it cant get any simpler than this ..

  3. Mark 15. Sep, 2011 at 9:18 pm #

    Can you give us the a downloadable source code for this? Thanks!

    • Anonymous 07. May, 2012 at 2:29 am #

      great article man…. Thanks

  4. mem 30. Oct, 2011 at 11:26 am #

    Very good tut, thanks

  5. Chandrasekhar Azad 24. Jan, 2012 at 9:37 am #

    simply super . i hope this will help the people who are just new to Android

  6. PaulK 31. May, 2012 at 4:37 am #

    thank you so much this really helped me out good on ya !!!

  7. Abhishek 27. Jul, 2012 at 4:19 am #

    thanks a lot for such a great article..
    but how to refer the progress in the ProgressTask Class.

  8. Puja 12. Sep, 2012 at 4:30 am #

    thank for your article.

    my modification :)

    package com.example.asynctasktest;

    import android.app.Activity;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.os.SystemClock;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ProgressBar;
    import android.widget.Toast;

    public class MainActivity extends Activity {
    //
    private ProgressBar progress;
    Button buttonStartProgress;
    Button buttonCancel;

    class ProgressTask extends AsyncTask {

    @Override
    protected void onPreExecute() {
    // initialize the progress bar
    //Toast, popup text when the progress is begin
    Toast.makeText(MainActivity.this,
    “Progress begin”, Toast.LENGTH_LONG).show();
    // set maximum progress to 100.
    progress.setMax(100);

    }

    @Override
    protected void onCancelled() {
    // stop the progress back to 0
    progress.setMax(0);

    }

    @Override
    protected Void doInBackground(Integer… params) {
    // get the initial starting value
    int start = params[0];
    // increment the progress
    for (int i = start; i <= 100; i += 5) {
    try {
    boolean cancelled = isCancelled();
    // if async task is not cancelled, update the progress
    if (!cancelled) {
    publishProgress(i);
    // delay progress
    SystemClock.sleep(1000);

    }

    } catch (Exception e) {
    Log.e("Error", e.toString());
    }

    }
    return null;
    }

    @Override
    protected void onProgressUpdate(Integer… values) {
    // increment progress bar by progress value
    progress.setProgress(values[0]);
    }

    @Override
    protected void onPostExecute(Void result) {
    // async task finished
    Log.v("Progress", "Finished");
    //Toast, popup text when the progress is finshed
    Toast.makeText(MainActivity.this,
    "Progress finished", Toast.LENGTH_LONG).show();
    //when the progress finished. the button can click again
    buttonStartProgress.setClickable(true);
    }

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    //call id function from main.xml
    buttonStartProgress = (Button)findViewById(R.id.btn);
    buttonCancel = (Button)findViewById(R.id.btnCancel);
    progress = (ProgressBar)findViewById(R.id.progress);

    //create click method function for start progress
    buttonStartProgress.setOnClickListener(new Button.OnClickListener(){
    @Override
    public void onClick(View v) {
    ProgressTask task=new ProgressTask();
    switch(v.getId()){
    case R.id.btn:
    //execute progress starting from 10 to 100
    task.execute(10);
    //when the progressbarr still in progress. the button cant click
    buttonStartProgress.setClickable(false);
    break;
    }
    }
    });

    //create click method function for cancel progress
    buttonCancel.setOnClickListener(new Button.OnClickListener(){
    @Override
    public void onClick(View v) {
    ProgressTask task=new ProgressTask();
    switch(v.getId()){
    case R.id.btnCancel:
    task.cancel(true);
    break;
    }

    }
    });

    }
    }

Trackbacks/Pingbacks

  1. Android App Development:Threading part 2: Async Tasks | blog - 08. Dec, 2011

    [...] http://mobileorchard.com/android-app-developmentthreading-part-2-async-tasks/ This entry was posted in Uncategorized by yongzhen. Bookmark the permalink. [...]

Leave a Reply

© 2008-2051 • Mobile Orchard and the Bar-Tree Logo are service marks. ContactAdvertise