Tuesday, July 19, 2011

Threads and Handlers for Android

Any mobile software development needs to be done with an awareness of the end user experience. This is true in any other domain as well. But special mention here on mobile development as end users are used to responsive apps on the mobile and any small delay is perceived as un-responsiveness or worse – that the application has hung.

One of the basic principles to provide a very responsive application is to handle any time consuming code in a separate thread – not the main thread or the UI thread as it is also known. So, it is very essential to understand about how to spawn new threads (worker or background threads) and how to come back to the parent thread.

How do the 2 threads (parent/UI and the worker threads) communicate? Here comes the Handler. By definition – “A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue.”

So, let us take the handler from the main thread and see how we can use it to communicate with a child thread.

When a handler is created, it is associated by default with the current thread. So, we have this piece of code in the main activity class:



Now, I spawn a new thread through a method that is called when I click a button. So, let us see the button piece of code first:

private Handler messageHandler = new Handler() {
};
public void handleMessage(Message msg) {
super.handleMessage(msg);
progressDialog.dismiss();
}

start = (Button) findViewById(R.id.Button01);

start.setOnClickListener(new OnClickListener() {});
@Override
public void onClick(View arg0) {
fetchData();
}
Now, on click of the button, the fetchData() method is invoked. Assuming that this is a very time consuming task, I will spawn a thread and do the task and return from that thread as shown in the code below:

protected void fetchData() {


progressDialog = ProgressDialog.show(this, "", "Doing...");


new Thread() {


public void run() {
try {
    Thread.sleep(800);} catch (InterruptedException e) {
}
messageHandler.sendEmptyMessage(0);
}
       }.start();
    }


Since it is time consuming, I am starting a ProgressDialog just to inform the end user that some activity is happening. Then, I start the thread, make it sleep for 800 milliseconds and send back an empty message through the message handler. The messageHandler.sendEmptyMessage(0) is the callback on the parent thread’s messageHandler to inform that the child thread has finished its work. In this example I am sending an empty message. But this can be the means of communication and exchange of data from the child thread to the parent Thread.

Now the control returns to handleMessage() call back method. That method shown in the beginning just dismisses the progressDialog.

In real life cases, within this thread we can do things like calling web-services, calling web-sites to fetch specific data or doing network IO operations and returning actual data that needs to be displayed on the front-end.

I will take up an example of an HTTP call invoked through such a thread in the next tutorial.

Also note that the Android UI toolkit is not thread-safe and must always be manipulated on the UI thread only. So the child thread should return all data and the painting of the UI should be left to the main thread or any UI specific thread.

There is a better way of handling this through the use of AsyncTask, a utility class available from SDK 1.5 onwards. It was available as UserTask earlier.

No comments:

Post a Comment