: Beginning Android

Messages

Messages

To send a Message to a Handler, first invoke obtainMessage() to get the Message object out of the pool. There are a few flavors of obtainMessage(), allowing you to just create empty Message objects, or ones populated with message identifiers and arguments. The more complicated your Handler processing needs to be, the more likely it is you will need to put data into the Message to help the Handler distinguish different events.

Then, you send the Message to the Handler via its message queue, using one of the following sendMessage...() family of methods:

sendMessage() puts the message on the queue immediately

sendMessageAtFrontOfQueue() puts the message on the queue immediately, and moreover puts it at the front of the message queue (versus the back, as is the default), so your message takes priority over all others

sendMessageAtTime() puts the message on the queue at the stated time, expressed in the form of milliseconds based on system uptime (SystemClock.uptimeMillis())

sendMessageDelayed() puts the message on the queue after a delay, expressed in milliseconds

To process these messages, your Handler needs to implement handleMessage(), which will be called with each message that appears on the message queue. There, the handler can update the UI as needed. However, it should still do that work quickly, as other UI work is suspended until the Handler is done.

For example, lets create a ProgressBar and update it via a Handler. Here is the layout from the Threads/Handler sample project. This sample code along with all others in this chapter can be found in the Source Code section athttp://apress.com.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ProgressBar android:id="@+id/progress"

android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>

The ProgressBar, in addition to setting the width and height as normal, also employs the style property, which I wont cover in detail in this book. Suffice it to say, style property indicates this ProgressBar should be drawn as the traditional horizontal bar showing the amount of work that has been completed.

Here is the Java:

package com.commonsware.android.threads;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ProgressBar;
publicclass HandlerDemoextends Activity {
ProgressBar bar;
Handler handler =newHandler() {
@Override
public voidhandleMessage(Message msg) {
bar.incrementProgressBy(5);
}
};
boolean isRunning =false;
@Override
public voidonCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
bar = (ProgressBar)findViewById(R.id.progress);
}
public voidonStart() {
super.onStart();
bar.setProgress(0);
Thread background =newThread(newRunnable() {
public voidrun() {
try {
for (int i=0; i<20 && isRunning; i++) {
Thread.sleep(1000);
handler.sendMessage(handler.obtainMessage());
}
}catch (Throwable t) {
// just end the background thread
}
}
});
isRunning =true;
background.start();
}
public voidonStop() {
super.onStop();
isRunning =false;
}
}

As part of constructing the Activity, we create an instance of Handler, with our implementation of handleMessage(). Basically, for any message received, we update the ProgressBar by 5 points, then exit the message handler.

In onStart(), we set up a background thread. In a real system, this thread would do something meaningful. Here, we just sleep one second, post a Message to the Handler, and repeat for a total of 20 passes. This, combined with the 5-point increase in the ProgressBar position, will march the bar clear across the screen, as the default maximum value for ProgressBar is 100. You can adjust that maximum via setMax(), such as setting the maximum to be the number of database rows you are processing, and updating once per row.

Note that we thenleave onStart(). This is crucial. The onStart() method is invoked on the activity UI thread, so it can update widgets and anything else that affects the UI, such as the title bar. However, that means we need to get out of onStart(), both to let the Handler get its work done, and also so Android does not think our activity is stuck.

The resulting activity is simply a horizontal progress bar (see Figure 15-1).


Figure 15-1.The HandlerDemo sample application


: 0.169. /Cache: 2 / 0