Asynchronous Tasks

When I first learned Async tasks they were a bit daunting. But after having to use them for a personal project of mine, they are actually quite simple to implement and use. So I’m hoping this quick little tutorial will clear up a few questions you might have had about how they work and can be implemented into your own applications.

What are they?

The main thread in Android is the UI thread. All of the actions that take place in the UI are all put onto a queue and then are executed in a FIFO manner. For instance if you were to select something on the screen whether it be a button or checkbox, that checkbox/button has to be redrawn on the screen and thus that action of redrawing is put into the queue. Pressing another button or selecting another object will then also be put into the queue. So if you are sharing this thread with long operations and calculations it could drastically slow down the speed and functionality of your application. So to get around this barrier you can use Async tasks.

What do they do?

Async tasks allow you to preform background operations and publish results to the UI thread without having to manipulate threads or handlers. This is DIFFERENT from a service because a service is not its own separate process.

How to create one

So in this tutorial I will show you how to create and implement a simple timer Async task to show the true nature of using an Async task. So lets say you were to create an activity and try to keep time while computing calculations or running functions. Those functions and calculations would throw off the timer because before it could increment the timer it would have to wait for the previous functions/calculations to finish. So we need to create an Async task that keeps time and runs independently of the application.

Below we have the basic structure of the Async task. First create a class that EXTENDS the AsyncTask class. The 3 type parameters that follow the word AsyncTask reference the type of parameter you will be passing in, the type of parameter that you will be publishing as progress while this task is executing, and lastly the third parameter is the type of return value you will have when the task finishes. For my demonstration below my task will be receiving integers, publishing integers, and lastly returning a string stating that the task has finished.


import android.os.AsyncTask;
import android.util.Log;

public class Timer extends AsyncTask<Integer, Integer, String>{

    @Override
    protected String doInBackground(Integer... params) {

        return "Finished";
    }
}

For my example I’m only @Override-ing the doInBackground function. It’s the only function necessary for your Async task to function. This is the location where you put the code that will keep track of our simple timer. From the main activity I’m passing in an integer that tells my timer how long to run for in terms of seconds.

Integer…params means you will be receiving an array of integers so if I’m only passing in one integer (timerLength), then to receive the length I reference it like an array. Int roundLength = params[0]; We also have an integer named startRound to tell the timer where to begin. Typically you want this always be 0. But who knows maybe your application may need it to start at something other than that. You could always pass in another integer in the params and reference it startRound = params[1]; assuming the integer you want to be the startRound is passed second. If you are passing in more than one integer it needs to be an array that’s passed in as a parameter to the execute function that starts the doInBackground function of the Async task.


public class RoundTimer extends AsyncTask<Integer, Integer, String>{

    boolean done = false;

    @Override
    protected String doInBackground(Integer... params) {
        int roundLength = params[0];
        int startRound = 0;

        while(startRound < roundLength && done == false)
        {
            try{
                Thread.sleep(1000); // sleeps for 1 second
               }
            catch(InterruptedException e) {
                   e.printStackTrace();
               }
            startRound++; // increment by a second
        }
        return "Finished";
    }
}

In the above reference of code I added a new variable named done. If we need to set up a way for the timer to end before it comes to a finish we can now do that. For instance say the user needs to end the app before the timer finishes. So to avoid getting a force close we should create a way to end the timer early. Now we need to add a new function to end the timer early. Next let’s add a function to find out the state of the timer so we can do other processes in the main activity


public void quit() {
    done = true;
}

public boolean getCondition() {
    return done;
}

Now we need to create a use for this task in our main Activity. So below is my onCreate function with the RoundTimer class created as a global.


RoundTimer roundtimer = new RoundTimer();

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

    roundtimer.execute(90); //set timer for 90 seconds

    while(roundtimer.getCondition() == false) //while the round is still going do stuff
    {
     //do stuff while the round is going…
    }

}

We also need to override the onDestroy method if for whatever reason the user decides to leave the application while the timer is going. So below is our onDestroy method overridden.


@Override
public void onDestroy() {
super.onDestroy();

    roundTimer.quit();
}

Hope this helps you if you’re looking for a simple way to use an Async task.

About Andrew Rubiano

Computer Science major looking to pursue a master's degree in artificial intelligence after i complete my degree here at Florida State University. I love how popular mobile applications have become and definitely think they will be a huge part of our lives in the upcoming years. Im happy FSU has a class in mobile programming so i can be better prepared for the future.