This section shows you how to send data to objects in the UI thread in the task. This feature allows you to work in the background thread and display the results in the UI thread after completion.
Define a Handler in the UI thread
Handler is part of the Android system thread management framework. A Handler object receives the message and runs the code to process the message. Normally, you create a Handler for a new thread, but you can also create a Handler for an existing thread. When you connect the Handler to the UI thread, the code that handles the message will run on the UI thread.
Instantiate the Handler object in the constructor of the class that creates the thread pool and save it in a global variable. Instantiated with Handler (Looper) method, connect to the UI thread, and constructed using Looper object, which is also part of the Android system thread management framework. The Looper class has a static method getMainLooper() to get the Looper object of the UI thread. like:
private PhotoManager() {
...
// Defines a Handler object that's attached to the UI thread
mHandler = new Handler(()) {
...
In Handler, override handleMessage(). The Android system will call this method when the thread managed by the Handler receives a new message. All Handler objects of a specified thread will receive the same message.
/*
* handleMessage() defines the operations to perform when
* the Handler receives a new Message to process.
*/
@Override
public void handleMessage(Message inputMessage) {
// Gets the image task from the incoming Message object.
PhotoTask photoTask = (PhotoTask) ;
...
}
...
}
}
Move data from task to UI thread
To move data from the task of the background thread to the object of the UI thread, first save the UI object referenced to the data and task object, and then pass the task object and status code to the Handler object. In this object, send a message containing the status and task objects to the Handler. Because the Handler runs on the UI thread, it can move data to the UI object.
Store data in task objects
For example, this is a Runnable that runs in a background thread, which parses the Bitmap and saves it to its parent object. Runnable also saves the status code DECODE_STATE_COMPLETED.
// A class that decodes photo files into Bitmaps
class PhotoDecodeRunnable implements Runnable {
...
PhotoDecodeRunnable(PhotoTask downloadTask) {
mPhotoTask = downloadTask;
}
...
// Gets the downloaded byte array
byte[] imageBuffer = ();
...
// Runs the code for this task
public void run() {
...
// Tries to decode the image buffer
returnBitmap = (
imageBuffer,
0,
,
bitmapOptions
);
...
// Sets the ImageView Bitmap
(returnBitmap);
// Reports a status of "completed"
(DECODE_STATE_COMPLETED);
...
}
...
}
...
PhotoTask also contains an ImageView reference to display Bitmap. Although the reference Bitmap and ImageView are in the same object, because they are not in the UI thread, you cannot directly let the ImageView display Bitmap.
Send status step by step along the object hierarchy
PhotoTask holds references to the decoded data and the View object that displays the data. It receives the status code from the PhotoDecodeRunnable and transmits it along the referenced objects and Handler instances in the thread pool.
public class PhotoTask {
...
// Gets a handle to the object that creates the thread pools
sPhotoManager = ();
...
public void handleDecodeState(int state) {
int outState;
// Converts the decode state to the overall state.
switch(state) {
case PhotoDecodeRunnable.DECODE_STATE_COMPLETED:
outState = PhotoManager.TASK_COMPLETE;
break;
...
}
...
// Calls the generalized state method
handleState(outState);
}
...
// Passes the state to PhotoManager
void handleState(int state) {
/*
* Passes a handle to this task and the
* current state to the class that created
* the thread pools
*/
(this, state);
}
...
}
Move data to UI
PhotoManager receives the status code and the handle of the PhotoTask object from the PhotoTask object. Because the state is TASK_COMPLETE, create a Message containing the state and task objects and send it to the Handler.
public class PhotoManager {
...
// Handle status messages from tasks
public void handleState(PhotoTask photoTask, int state) {
switch (state) {
...
// The task finished downloading and decoding the image
case TASK_COMPLETE:
/*
* Creates a message for the Handler
* with the state and the task object
*/
Message completeMessage =
(state, photoTask);
();
break;
...
}
...
}
Finally, () checks the status code for each incoming Message. If the status code is TASK_COMPLETE, the task is completed. The PhotoTask object in Message contains Bitmap and ImageView. Because() runs in the UI thread, it can safely set Bitmap for ImageView.