Page 1 of 1

Easy Android Threading Using AsyncTask

#1 H3R3T1C  Icon User is offline

  • Android Expert
  • member icon

Reputation: 276
  • View blog
  • Posts: 757
  • Joined: 30-March 07

Posted 17 September 2011 - 05:19 PM

In this tutorial you will learn how to properly thread your Android application using an AsyncTask!

For the purposes of this tutorial we well be creating an application that counts to ten seconds but the AsyncTask can be adapted to do all sorts of threading such as downloading a file, doing some process intensive task, ect..

Important: Due to a bug within the forums some method names and class names have been made lowercase instead of uppercase! For example onclickListener should have an uppercase O and an uppercase C in it! if you are getting errors in your code remember the Java stander for naming class where class names start with an uppercase letter and ever new word in the name starts with an uppercase letter and same goes for method names except they start with a lowercase letter and ever new word starts with an uppercase letter!

To begin we first need to create a new Android! Create a new Android application with the following settings:
Posted Image

Now that our new project has been created open up main.xml under res -> layout. Since this is not a tutorial on GUI programming I will just be providing you with the code.

main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TextView android:id="@+id/textView1" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_weight="1" android:text="0 seconds" android:gravity="center"></TextView>
    <LinearLayout android:layout_height="wrap_content" android:id="@+id/linearLayout1" android:layout_width="fill_parent" android:orientation="horizontal" android:layout_weight=".5">
        <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="Start" android:layout_gravity="bottom"></Button>
        <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="Stop" android:layout_gravity="bottom"></Button>
    </LinearLayout>
</LinearLayout>




Once that is done open up Main.java under src -> com.h3r3t1c.tutorial.async.
Now with Main.java open we need to create a new method in it called private void initonclickListener(). The purpose of this method is to attach an onclickListener to our buttons! Put the following code in for that new method

    private void initonclickListener()
    {
    	onclickListener click = new onclickListener(){

			@Override
			public void onclick(View arg0) {
				switch(arg0.getId())
				{
					case R.id.button1:// stop
					{
						stopThread();
						break;
					}
					case R.id.button2:// start
					{
						startThread();
						break;
					}
				}
			}};
			findViewById(R.id.button1).setonclickListener(click);
			findViewById(R.id.button2).setonclickListener(click);
    }



Also don't forget to call this method from your onCreate method like so:
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        initonclickListener();// call to init our onclicklistenrers for our buttons!
    }



Now as you may noticed you will have to red underlines in our initonclickListener() method because we have two undeclared methods ( startThread() and stopThread()) so we need to create those method. Under our initonclickListener method add the following code:

Method skeletons for stopThread() and startThread() methods
private void startThread()
    {
    	
    }
    private void stopThread()
    {
    	
    }



Right now this is only the skeletons for the methods but we are going to be filling them in very soon!

Now its time to actually crate our AsyncTask class. Under src -> com.h3r3t1c.tutorial.async create a new class called AsyncTimer.

Put the following code in for this new class (Explanations of the code follows):
package com.h3r3t1c.tutorial.async;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;

public class AsyncTimer extends AsyncTask<Void,Integer,Boolean>{

	private boolean isRunning;
	private boolean stop;
	private int seconds;
	private Context context;
	private onprogressUpdateListener listener;
	
	public AsyncTimer(Context c)
	{
		context = c;
	}
	public void setonprogressUpdateListener(onprogressUpdateListener l)
	{
		listener = l;
	}
	@Override
	protected Boolean doInBackground(Void... arg0) {
		
		stop  = false;
		isRunning = true;
		seconds = 0;
		this.publishProgress(seconds);
		while(seconds<10&&stop!=true)
		{
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {

				Log.e("AsyncTutorial", e.getMessage());
			}
			seconds++;
	 		this.publishProgress(seconds);
		}
		
		if(stop==false)
			return true;
		else 
			return false;
	}
	
	@Override
	protected void onCancelled() {
		stop = true;
		isRunning = false;
		Toast.makeText(context, "User stopped thread!", Toast.LENGTH_SHORT).show();
	}

	@Override
	protected void onPostExecute(Boolean result) {
		isRunning = false;
		if(result==true)
			Toast.makeText(context, "Running of 10 second timer complete!", Toast.LENGTH_SHORT).show();
	}

	@Override
	protected void onprogressUpdate(Integer... values) {
		listener.progressUpdate(values[0]);
	}
	public boolean getIsRunning()
	{
		return isRunning;
	}
	
	public interface onprogressUpdateListener
	{
		public void progressUpdate(int i);
	}

}



As you can see our class extends AsyncTask with the three different types of <Void,Integer,Boolean>. The following image illustrate and describes how to use this:
Posted Image
Image url: http://i.imgur.com/QNzuv.png

The doInBackground(...) method is where we put our code that needs to be run in the thread. In the case of this example there is where our counts is run!

The onCancelled() called when the user calls the cancel(<boolean>) method (which will be shown in the next part of the code we do). This method is run on the UI thread so we can show message or update UI components!

The onPostExecute(...) method is called once our doInBackground(...) method competes without cancel being called! This method is called on the UI thread so we can show message or update UI components!

The onprogressUpdate(...) method is called once we make make a call to publishProgress(...). This method is also run on the UI thread!

Now its time to go back to our Main.java and use our AsyncTimer!
In Main.java add the following private instance variable right above the onCreate method:

private AsyncTimer timer;



Now go down to the startThread() method and fill it in with the following code:

        if(timer!=null&&timer.getIsRunning()==true)
    	{
    		Toast.makeText(this, "Timer is already running!", Toast.LENGTH_SHORT).show();
    		return;
    	}
    	timer = new AsyncTimer(this);// We need to make a new AsyncTime every time because it can only be executed once!
        timer.setonprogressUpdateListener(new onprogressUpdateListener(){

			@Override
			public void progressUpdate(int i) {
				((TextView)findViewById(R.id.textView1)).setText(i+" seconds");
			}
        	
        });
    	timer.execute(null);//This is were we start our thread! This is null because our param type is Void!



Then go down to the stopThread() and fill it in with the following code:

        if(timer==null || timer.getIsRunning()==false)
    	{
    		Toast.makeText(this, "Timer is not running!", Toast.LENGTH_SHORT).show();
    		return;
    	}
    	timer.cancel(true);// this will make the call to the onCancelled() method in the AsyncTime class!



At the end this is what our Main.java should look like:

package com.h3r3t1c.tutorial.async;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.onclickListener;
import android.widget.TextView;
import android.widget.Toast;

import com.h3r3t1c.tutorial.async.AsyncTimer.onprogressUpdateListener;

public class Main extends Activity {
	
    private AsyncTimer timer;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        initonclickListener();
    }
    private void initonclickListener()
    {
    	onclickListener click = new onclickListener(){

			@Override
			public void onclick(View arg0) {
				switch(arg0.getId())
				{
					case R.id.button1:// stop
					{
						stopThread();
						break;
					}
					case R.id.button2:// start
					{
						startThread();
						break;
					}
				}
			}};
			findViewById(R.id.button1).setonclickListener(click);
			findViewById(R.id.button2).setonclickListener(click);
    }
    private void startThread()
    {
    	if(timer!=null&&timer.getIsRunning()==true)
    	{
    		Toast.makeText(this, "Timer is already running!", Toast.LENGTH_SHORT).show();
    		return;
    	}
    	timer = new AsyncTimer(this);// We need to make a new AsyncTime every time because it can only be executed once!
        timer.setonprogressUpdateListener(new onprogressUpdateListener(){

			@Override
			public void progressUpdate(int i) {
				((TextView)findViewById(R.id.textView1)).setText(i+" seconds");
			}
        	
        });
    	timer.execute(null);//This is were we start our thread! This is null because our param type is Void!
    	
    }
    private void stopThread()
    {
    	if(timer==null || timer.getIsRunning()==false)
    	{
    		Toast.makeText(this, "Timer is not running!", Toast.LENGTH_SHORT).show();
    		return;
    	}
    	timer.cancel(true);// this will make the call to the onCancelled() method in the AsyncTime class!
    }
}



Thats it! You should now have learned enough to be able to create your own AsyncTask class to handle all your threading needs!

Full project: http://www.sendspace.com/pro/dl/etgxuv

Is This A Good Question/Topic? 2
  • +

Page 1 of 1