Communicate with the UI thread

The previous guide, which teaches you how to Run code on a thread pool
thread, shows you how to start a task on a thread managed by
ThreadPoolExecutor. This final lesson shows you how to send data
from the task to objects running on the user interface (UI) thread. This feature allows your
tasks to do background work and then move the results to UI elements such as bitmaps.

Every app has its own special thread that runs UI objects such as View
objects; this thread is called the UI thread. Only objects running on the UI thread have access
to other objects on that thread. Because tasks that you run on a thread from a thread pool
aren't running on your UI thread, they don't have access to UI objects. To move data
from a background thread to the UI thread, use a Handler that's
running on the UI thread.

Define a handler on the UI thread

Handler is part of the Android system's framework for managing threads. A
Handler object receives messages and runs code to handle the messages.
Normally, you create a Handler for a new thread, but you can
also create a Handler that's connected to an existing thread.
When you connect a Handler to your UI thread, the code that handles messages
runs on the UI thread.

Instantiate the Handler object during the construction of the class that
creates your thread pools, and store the object in a global variable. Connect it to the UI
thread by instantiating it with the Handler(Looper)
constructor. This constructor uses a Looper object, which is another part of
the Android system's thread management framework. When you instantiate a
Handler based on a particular Looper instance, the
Handler runs on the same thread as the Looper.
For example:

Java

Inside the Handler, override the handleMessage() method. The Android system invokes this method when it receives a new message
for a thread it's managing; all of the Handler objects for a particular
thread receive the same message. For example:

Move data from a task to the UI thread

To move data from a task object running on a background thread to an object on the UI thread,
start by storing references to the data and the UI object in the task object. Next, pass the
task object and a status code to the object that instantiated the Handler.
In this object, send a Message containing the status and the task object to
the Handler. Because Handler is running on the UI thread,
it can move the data to the UI object.

Store data in the task object

For example, here's a Runnable, running on a background thread, that decodes a
Bitmap and stores it in its parent object PhotoTask.
The Runnable also stores the status code DECODE_STATE_COMPLETED.

PhotoTask also contains a handle to the ImageView that
displays the Bitmap. Even though references to
the Bitmap and ImageView are in the same object,
you can't assign the Bitmap to the ImageView,
because you're not currently running on the UI thread.

Instead, the next step is to send this status to the PhotoTask object.

Send status up the object hierarchy

PhotoTask is the next higher object in the hierarchy. It maintains references to
the decoded data and the View object that will show the data. It receives
a status code from PhotoDecodeRunnable and passes it along to the object that
maintains thread pools and instantiates Handler:

Move data to the UI

From the PhotoTask object, the PhotoManager object receives a status
code and a handle to the PhotoTask object. Because the status is
TASK_COMPLETE, creates a Message containing the state and task
object and sends it to the Handler: