Книга: 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, let’s 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 at http://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 won’t 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;
public class HandlerDemo extends Activity {
ProgressBar bar;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
bar.incrementProgressBy(5);
}
};
boolean isRunning = false;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
bar = (ProgressBar)findViewById(R.id.progress);
}
public void onStart() {
super.onStart();
bar.setProgress(0);
Thread background = new Thread(new Runnable() {
public void run() {
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 void onStop() {
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 then leave 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
- 8.4.2. Sending and Receiving Messages
- 5.1.4. Boot Messages
- 9.4.1.Messages
- Send Messages to NetWare Users
- Routing Messages
- Delivering Messages to Local Addresses
- Control Messages
- Handling Control Messages
- 7.6.2 Sending and Receiving Messages
- Placing Calls and Messages
- ? Enable Power Management Notification Messages
- Macros for Debug Messages