Skip to content

aviyehuda.com

Menu
  • Open Source
  • Android
  • Java
  • Others
  • Contact Me
  • About Me
Menu

Android – Multithreading in a UI environment

Posted on 20/12/2010



android

Why do we need multithreading in Android applications?
Let’s say you want to do a very long operation when the user pushes a button.
If you are not using another thread, it will look something like this:

((Button)findViewById(R.id.Button01)).setOnClickListener(           
             new OnClickListener() {
		
			@Override
			public void onClick(View v) {
            int result = doLongOperation();
            updateUI(result);
			}
		});

What will happen?
The UI freezes. This is a really bad UI experience. The program may even crash.

The problem in using threads in a UI environment
So what will happen if we use a Thread for a long running operation.
Let’s try a simple example:

((Button)findViewById(R.id.Button01)).setOnClickListener(
new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				
				(new Thread(new Runnable() {
					
					@Override
					public void run() {
                    int result = doLongOperation();
                    updateUI(result);
					}
				})).start();
				
			}

The result in this case is that the application crashes.
12-07 16:24:29.089: ERROR/AndroidRuntime(315): FATAL EXCEPTION: Thread-8
12-07 16:24:29.089: ERROR/AndroidRuntime(315): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
12-07 16:24:29.089: ERROR/AndroidRuntime(315): at ...

Clearly the Android OS wont let threads other than the main thread change UI elements.

But why?
Android UI toolkit, like many other UI environments, is not thread-safe.

The solution

  • A queue of messages. Each message is a job to be handled.
  • Threads can add messages.
  • Only a single thread pulls messages one by one from the queue.

The same solution was implemented in swing (Event dispatching thread
and SwingUtilities.invokeLater() )

Handler
The Handler is the middleman between a new thread and the message queue.

Option 1 – Run the new thread and use the handler to send messages for ui changes

final Handler myHandler = new Handler(){
	@Override
public void handleMessage(Message msg) {
		updateUI((String)msg.obj);
}
	
};

(new Thread(new Runnable() {
	
	@Override
	public void run() {
		Message msg = myHandler.obtainMessage();
		
		msg.obj = doLongOperation();
		
		myHandler.sendMessage(msg);
	}
})).start();

* keep in mind that updating the UI should still be a short operation, since the UI freezes during the updating process.

Other possibilities:
handler.obtainMessage with parameters
handler.sendMessageAtFrontOfQueue()
handler.sendMessageAtTime()
handler.sendMessageDelayed()
handler.sendEmptyMessage()

Option 2 – run the new thread and use the handler to post a runnable which updates the GUI.

final Handler myHandler = new Handler();
				
				(new Thread(new Runnable() {
					
					@Override
					public void run() {
						final String res = doLongOperation();
						myHandler.post(new Runnable() {
							
							@Override
							public void run() {
								updateUI(res);
							}
						});
					}
				})).start();
				
			}

android multithreading

Looper
If we want to dive a bit deeper into the android mechanism we have to understand what is a Looper.
We have talked about the message queue that the main thread pulls messages and runnables from it and executes them.
We also said that each handler you create has a reference to this queue.
What we haven’t said yet is that the main thread has a reference to an object named Looper.
The Looper gives the Thread the access to the message queue.
Only the main thread has executes to the Looper by default.

Lets say you would like to create a new thread and you also want to take advantage of the message queue functionality in that thread.

(new Thread(new Runnable() {

						@Override
						public void run() {

							innerHandler = new Handler();
							
							Message message = innerHandler.obtainMessage();
							innerHandler.dispatchMessage(message);
						}
					})).start();

Here we created a new thread which uses the handler to put a message in the messages queue.

This will be the result:
12-10 20:41:51.807: ERROR/AndroidRuntime(254): Uncaught handler: thread Thread-8 exiting due to uncaught exception
12-10 20:41:51.817: ERROR/AndroidRuntime(254): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
12-10 20:41:51.817: ERROR/AndroidRuntime(254): at android.os.Handler.(Handler.java:121)
12-10 20:41:51.817: ERROR/AndroidRuntime(254): at ...

The new created thread does not have a Looper with a queue attached to it. Only the UI thread has a Looper.
We can however create a Looper for the new thread.
In order to do that we need to use 2 functions: Looper.prepare() and Looper.loop().

(new Thread(new Runnable() {

					@Override
					public void run() {

						Looper.prepare();
						innerHandler = new Handler();
								
						Message message = innerHandler.obtainMessage();
						innerHandler.dispatchMessage(message);
						Looper.loop();
					}
				})).start();

If you use this option, don’t forget to use also the quit() function so the Looper will not loop for ever.

@Override
	protected void onDestroy() {
		innerHandler.getLooper().quit();
		super.onDestroy();
	}

AsyncTask
I have explained to you that a Handler is the new thread’s way to communicate with the UI thread.
If while reading this you were thinking to yourself, isn’t there an easier way to do all of that… well, you know what?! There is.

Android team has created a class called AsyncTask which is in short a thread that can handle UI.

Just like in java you extend the class Thread and a SwingWorker in Swing, in Android you extend the class AsyncTask.
There is no interface here like Runnable to implement I’m afraid.

class MyAsyncTask extends AsyncTask<Integer, String, Long> {
    	
    	@Override
    	protected Long doInBackground(Integer... params) {
    		
    		long start = System.currentTimeMillis();
    		for (Integer integer : params) {
    			publishProgress("start processing "+integer);
    			doLongOperation();
    			publishProgress("done processing "+integer);
    		}
    		
    		return start - System.currentTimeMillis();
    	}

    	
    	
    	@Override
    	protected void onProgressUpdate(String... values) {
    		updateUI(values[0]);
    	}
    	
    	@Override
    	protected void onPostExecute(Long time) {
    		updateUI("Done with all the operations, it took:" +
                                     time + " millisecondes");
    	}

    	@Override
    	protected void onPreExecute() {
    		updateUI("Starting process");
    	}
    	
    	
    	public void doLongOperation() {
    		
    		try {
    			Thread.sleep(1000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		
    	}
    	
    }

This is how you start this thread:

MyAsyncTask aTask = new MyAsyncTask();
aTask.execute(1, 2, 3, 4, 5);

AsyncTask defines 3 generic types:
AsyncTask<{type of the input}, {type of the update unit}, {type of the result}>
You don’t have to use all of them – simply use ‘Void’ for any of them.

Notice that AsyncTask has 4 operations, which are executed by order.
1. onPreExecute() – is invoked before the execution.
2. onPostExecute() – is invoked after the execution.
3. doInBackground() – the main operation. Write your heavy operation here.
4. onProgressUpdate() – Indication to the user on progress. It is invoked every time publishProgress() is called.

* Notice: doInBackground() is invoked on a background thread where onPreExecute(), onPostExecute() and onProgressUpdate() are invoked on the UI thread since their purpose is to update the UI.

Android developer website also mentions these 4 rules regarding the AsyncTask:

  • The task instance must be created on the UI thread.
  • execute(Params…) must be invoked on the UI thread.
  • Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params…), onProgressUpdate(Progress…) manually.
  • The task can be executed only once (an exception will be thrown if a second execution is attempted.)

Timer + TimerTask
Another option is to use a Timer.
Timer is a comfortable way to dispatch a thread in the future, be it once or more.

Instead of doing this:

Runnable threadTask = new Runnable() {
	
	@Override
	public void run() {
		
		while(true){
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			doSomething();
		}
	}
};
	
(new Thread(threadTask)).start();

do this:

TimerTask timerTask = new TimerTask() {		
	@Override
	public void run() {
		doSomething();			
	}
}; 

Timer timer = new Timer();
timer.schedule(timerTask, 2000,2000);

which is a bit more elegant.

Bare in mind, you still have to use Handler if you need to do UI operations.

Download sources:

zip Download demo project 1
zip Download demo project 2

33 thoughts on “Android – Multithreading in a UI environment”

  1. P7h says:
    21/12/2010 at 21:21

    Very neatly written and explained.
    But only gripe is, code could have used better formatting / syntax highlighting JS.
    Even otherwise, an excellent article.

    Reply
  2. Pingback: Android – Multithreading in a UI environment : Mike's burogu
  3. arthur says:
    05/01/2011 at 18:07

    What a great article. I have googled for a long time looking for a good explanation of the topic, and this one is the best I found. Thanks!

    Reply
  4. Purush says:
    21/01/2011 at 11:53

    Excellent article, Very clear.

    Reply
  5. Pepper says:
    15/03/2011 at 11:28

    so great article. Thanks!

    Reply
  6. Hom says:
    13/05/2011 at 09:04

    great article..got clear concept..thanks!

    Reply
  7. Kiran says:
    20/05/2011 at 08:50

    Good article to clear concepts !!

    Reply
  8. karan says:
    21/06/2011 at 14:12

    gooodddddddd

    Reply
  9. karan says:
    21/06/2011 at 14:15

    in multi threadind there is only one interface Runnable() ????????????????

    Reply
  10. Monish says:
    25/07/2011 at 11:12

    Thanks a lot, very useful…

    Reply
  11. vipin says:
    28/07/2011 at 12:58

    A very good article for understanding handler, looper, asynctask. I was reading about them for few days but not able to clear doubts. This article helped me a lot.
    Thanks

    Reply
  12. krishna K Mishra says:
    17/08/2011 at 21:32

    It’s really a great tutorial on Complete thread handling in android ..
    Thank you so much for publishing so nice tutorial….

    Reply
  13. Richard L. says:
    10/11/2011 at 22:30

    We have been doing programming without threads, with complexe systems and our UI wouldn’t freeze 🙂

    I guess there are many ways to create a piece of software, that will still what it is supposed to do. You can use threads or not and achieve the same thing.

    Reply
    1. Avi says:
      10/11/2011 at 22:59

      Hi Richard.
      If you don’t need threads that’s great.
      But the question is: what do you mean by “complex”.
      Some of the actions require more time than others.
      If for example, your application reads pictures from the internet, than I am afraid you will have to use threads, this action takes a few seconds.
      Bear in mind, that the main thread can not be busy for more than 5 seconds, otherwise the OS will pop an alert to the user asking him whether he wishes to close down the application.
      Thanks for your comment 🙂

      Reply
  14. Howard says:
    27/11/2011 at 16:55

    The Best!

    Reply
  15. Eric says:
    22/12/2011 at 07:38

    Thx, helped alot 🙂

    Reply
  16. Rui Pedrosa says:
    06/01/2012 at 12:18

    A simple but very useful explanation! thanks!

    Reply
  17. Karol says:
    14/01/2012 at 01:06

    Hi All the examples I see so far implement the Runnable object as inner class of the main UI Thread Activity. In my up I dont want to do this because my runnable does more things and it also extend TextView. Basically it is a timer that display minutes and second passed and does other things. I want it to be separate class but it does not work. Can someon post an example that uses runnable that modifies a UI but it is a separate class.

    Thanks

    Karol

    Reply
    1. Rhodderz says:
      12/02/2013 at 17:59

      Hey did you ever work out your problem as i have the same one.

      Reply
  18. neetika says:
    30/03/2012 at 09:38

    Really simple and useful explanation about threading.i was searching like this.thanks

    Reply
  19. Shirish says:
    10/05/2012 at 10:53

    Excellent article! Thanks!

    Reply
  20. Guest says:
    05/06/2012 at 23:17

    > Notice that AsyncTask has 4 operations, which are executed by order.

    Shouldn’t that “order” be 1,3,2 ????

    Reply
  21. Guest says:
    05/06/2012 at 23:19

    > The task can be executed only once (an exception will be
    > thrown if a second execution is attempted.)

    Once per ….. ?

    Per day?
    Per minute?
    After the first one finishes… you can start another?

    It says only *ONCE*? So you can NEVER execute this again?
    NEVER?

    So if I need this 10 times… I have to cut/paste all the code in… 10 times????

    Reply
    1. Anonymous says:
      24/07/2012 at 22:45

      No, you’d simply have to make a new instance of the object and call execute on that.

      Reply
  22. Pingback: Techbeast.net - Google Nexus 7 Announced - Techbeast.net
  23. Vasilis says:
    15/07/2012 at 23:13

    Really good…thanks!

    Reply
  24. Kiên says:
    19/07/2012 at 05:32

    huuuuuuuuuuuuuuuuuuuuuuuu, like like

    Reply
  25. Paolo says:
    26/03/2013 at 13:26

    Great tutorial! Thank you!

    Reply
  26. leafstyle says:
    17/04/2013 at 11:29

    十分感谢
    thanks!

    Reply
  27. Puru says:
    27/08/2013 at 12:55

    Great tutorial… Thanks for sharing..

    Reply
  28. karim medusa says:
    25/05/2014 at 08:39

    Tnx,very useful!

    Reply
  29. Pingback: Looper and Handler – Site Title
  30. Pingback: What exactly does the post method do? - ExceptionsHub

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *


About Me

REFCARD – Code Gems for Android Developers

Categories

  • Android
  • AWS
  • AWS EMR
  • bluetooth
  • Chrome extension
  • ClientSide
  • Clover
  • Coding Coventions
  • Data Lake
  • General
  • GreaseMonkey
  • Hacks
  • hibernate
  • hibernate validator
  • HTML5
  • HtmlUnit
  • Image Manipulation
  • Java
  • Java Technologies
  • JavaScript
  • Java_Mail
  • JEE/Network
  • Job searching
  • Open Source
  • Pivot
  • projects
  • Pure Java
  • software
  • Spark
  • Trivia
  • Web development

Archives

  • March 2022 (1)
  • January 2022 (1)
  • January 2021 (1)
  • December 2018 (1)
  • August 2018 (1)
  • October 2013 (1)
  • March 2013 (1)
  • January 2013 (2)
  • July 2012 (1)
  • April 2012 (1)
  • March 2012 (1)
  • December 2011 (1)
  • July 2011 (1)
  • June 2011 (1)
  • May 2011 (2)
  • January 2011 (1)
  • December 2010 (1)
  • November 2010 (3)
  • October 2010 (4)
  • July 2010 (1)
  • April 2010 (2)
  • March 2010 (1)
  • February 2010 (2)
  • January 2010 (5)
  • December 2009 (10)
  • September 2009 (1)
 RSS Feed
1d96f52e7159fe09c7a3dd2a9816d166-332
©2023 aviyehuda.com | Design: Newspaperly WordPress Theme