Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art
Writing Recipes
Sending messages between threads using activity thread queue and Handler class
Contributed by Vladimir Kroz 2010-11-19 02:53:43 (updated 2011-12-16 03:33:32)
In Published Edition? Yes
Minimum Version 1.5

You need to pass information or data from a Service or other background task, to an Activity. Since Activities run on the UI thread it is not safe to call them from a background thread.

  • Write a nested class that extends Android's Handler class; override the handleMessage() method which will read messages from thread queue;
  • Pass this Handler to the worker thread, usually via the worker class' constructor;
  • In the worker thread, post messages using the various obtainMessage() and sendMessage() methods;
  • This will cause the Activity to be called at the handleMessage() method, but on the event thread so you can safely update the GUI.

There are many situations when it is required to have a thread running in the background and send information to main Activity's UI thread. At the architectural level there are different approaches that can be taken:

  1. Use of Android AsyncTask class
  2. Start a new thread

Though using AsyncTask is very convenient, there are a situations when you really need to construct a worker thread by yourself. In such situation you likely will need to send some information back to Activity thread. Keep in mind that Android doesn't allow other threads to modify any content of main UI thread. Instead you're required to wrap data into Messages and send them through message queue. The implementation consists of two parts.

1) Add handler

Add an instance of Handler class to e.g., your MapActivity instance.

public class MyMap extends MapActivity {
    . . . 
    public Handler _handler = new Handler() {
		public void handleMessage(Message msg) {
			Log.d(TAG, String.format("Handler.handleMessage(): msg=%s", msg));
            // This is where main activity thread receives messages
            // Put here your handling of incoming messages posted by other threads

. . . .


2) Post Message

In the worker thread post a message to activity main queue whenever you need Add handler class instance to your MapActivity instance.

	 * Performs background job
	 class MyThreadRunner implements Runnable {
		// @Override
		public void run() {
			while (!Thread.currentThread().isInterrupted()) {
// Just dummy message -- real implementation will put some meaningful data in it
				Message msg = Message.obtain();
				msg.what = 999;
// Dummy code to simulate delay while working with remote server
				try {
				} catch (InterruptedException e) {
Comments (1)
Leave a comment
Edit History (6)
JimT-Utah said 2013-08-21 12:34:05 I can't make this recipe work I have an array of images that I want to display in sequence to represent the operation of a piece of hardware. When I loop through them in my MainActivity, everything goes as expected. What I really want to do, though, is run the sequence in a thread while I’m doing more important stuff in the main thread. I put the array and two classes inside my MainActivity class. When I compile my program, I get a “No enclosing instance of the type MainActivity.postPix is accessible in scope” error. What do I need to do to get it to work? int coil_array[] = { R.drawable.coil0, R.drawable.coil1, R.drawable.coil2, R.drawable.coil3, R.drawable.coil4, R.drawable.coil5, R.drawable.coil6, R.drawable.coil7 }; public class postPix extends MainActivity { public Handler _handler = new Handler() { @Override public void handleMessage(Message msg) { coil_image.setBackgroundResource(msg.what); super.handleMessage(msg); }; }; } public class display_loop implements Runnable { public void run() { int coil_index = 0; control_variable = true; while (control_variable) { if (MainActivity.current_state != state.Charging) control_variable = false; try { coil_index = (++coil_index) % 8; Message msg = Message.obtain(); msg.what = coil_index; ******** postPix.this._handler.sendMessage(msg); Thread.sleep(100); } catch (Exception ex) { String S = ex.getLocalizedMessage(); S = "Error" + S; } } return; } }