Android defines two classes in the android.os package that will often be the
cornerstones of the interthread communication in your multithreaded applications:
Handler
Looper
While creating an AsyncTask object hides the Handler and Looper details from you, in
some cases you need to use handlers and loopers explicitly, for example when you need
to post a Runnable to a thread other than the main thread.
you use a
Handler object to post a Runnable in a Looper’s message queue. Your application’s main
thread already has a message queue, so you don’t have to create one explicitly.
However, the threads you create do not come automatically with a message queue and
message loop, so you would have to create one yourself if needed. Listing 5-8 shows
how you can create a thread with a Looper.
Listing 5–8
public class MyThread extends Thread {
private static final String TAG = “MyThread”;
private Handler mHandler;
public MyThread(String name) {
super(name);
}
public Handler getHandler() {
return mHandler;
}
@Override
public void run() {
Looper.prepare(); // binds a looper to this thread
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
// process messages here
}
}
};
// the handler is bound to this thread’s looper
Looper.loop(); // don’t forget to call loop() to start the message loop
// loop() won’t return until the loop is stopped (e.g., when Looper.quit() is called)
}
}
Android provides an easier way to work with looper threads with the HandlerThread
class, which also makes it easier to avoid the potential race condition mentioned in
Listing 5–8, where getHandler() may still return null even after the thread has been
started. Listing 5–9 shows how to use the HandlerThread class.
Listing 5–9. Using the HandlerThread Class
public class MyHandlerThread extends HandlerThread {
private static final String TAG = "MyHandlerThread";
private Handler mHandler;
public MyHandlerThread(String name) {
super(name);
}
public Handler getHandler() {
return mHandler;
}
@Override
public void start() {
super.start();
Looper looper = getLooper(); // will block until thread’s Looper object is initialized
mHandler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
// process messages here
}
}
};
}
}