Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art

Creating a Responsive Application Using Threads

Author: Amir Alagic
Published? true -- FormatLanguage: W

Problem:

How to create a responsive application.

Solution:

A successful Android application has to be responsive and since all Activities, Broadcast Receivers and Services are running on the main application thread (UI thread), any time-consuming operations will block the UI. If such an operation takes more than five seconds, in Activities, the Android OS will show the standard "Application ... is not responding" error alert/dialog, often called an ANR for short.

Discussion:

To make your application responsive while some time-consuming operations are running on Android OS you have a few options. If you already know Java then you know that you can create class that extends Thread class and overrides public void run() method and then call start method on that object to run some time-consuming process. If your class already extends another class you can implement Runnable interface. And another different approach is to create your own class that extends Androids AsyncTask class but we will talk about AsyncTask in another recipe.

First we will discuss usage of Thread class.

public class NetworkConnection extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Thread thread = new Thread(new Runnable(){
		public void run() {
			getServerData();
		} 
     	}); 
    	thread.start();		
   }
}

As you see, when we start our activity in onCreate method we create a thread object that is constructed with a Runnable object. The Runnable method run() will be executed after we call start() method on the thread object. From here you can call another method or few other methods and operations that are time-consuming and that would otherwise block the main thread and make your application look unresponsive.

Often when we are done with the thread we get results that we want to present to the application user. If you try to update the GUI from the thread that you started (not the main thread) your application will crash. You can read error messages and see that the problem is in fact a thread other than the main UI thread tried to change UI on the main thread.

Of course it is possible to change UI with help of a Handler class.

In your activity create a final Handler object and within your public void run() method call its post() method.

final Handler handler = new Handler();

Thread thread = new Thread(new Runnable(){
    	public void run() {
    	handler.post(new Runnable(){
    		public void run() {
                    	//textView is a UI control created on the main thread
		    	textView.setText("Change Text");
		}
    				
    	});
         } 
       }); 
thread.start();	

Threads created and started in this way will continue to run even if the user leaves your application. To be sure that your thread(s) stop when the user leaves your application, before you call start() method on thread object set thread as daemon thread.

thread.setDaemon(true);

Beside that sometimes it can be useful to name the thread.

You can give a name to your thread(s) when you create the thread object

Thread thread = new Thread();
Thread thread = new Thread(runnable, "ThreadName1");

or you can call setName() method on thread object.

thread.setName("ThreadName2"); 

These names will not be visible to the user, but will show up in various diagnostic logs, to help you find which thread is causing problems.

micinski 2012-01-01 06:41:55.81 Creating explicit threads in Android is, in general, "probably a bad idea." There are many other threading utilities, AsyncTask, Services, and others, (Although noting that services should still fork off threads for long running background operations). It is rarely necessary to create a Runnable and fork off a thread, and perhaps this should be noted somewhere in the article?