A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
/* @param callback The callback interface in which to handle messages, or null.
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
*
* @hide
*/publicHandler(Callback callback, boolean async) {
...//省略
mLooper = Looper.myLooper();
if (mLooper == null) {
thrownew RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
Most interaction with a message loop is through the Handler class.
...
publicstaticvoidprepare() {
prepare(true);
}
privatestaticvoidprepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
thrownew RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
...
privateLooper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
...
/*
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/publicstatic @Nullable Looper myLooper() {
return sThreadLocal.get();
}
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/publicstaticvoidloop() {
final Looper me = myLooper();
...
final MessageQueue queue = me.mQueue;
...
for (;;) {
Message msg = queue.next(); // might blockif (msg == null) {
// No message indicates that the message queue is quitting.return;
}
...
msg.target.dispatchMessage(msg);
...
msg.recycleUnchecked();
}
}
/**
* ...
* <p class="note">While the constructor of Message is public, the best way to get
* one of these is to call {@link #obtain Message.obtain()} or one of the
* {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull
* them from a pool of recycled objects.</p>
*/publicfinalclassMessageimplementsParcelable {
...
publicint what;
public Object obj;
...
/*package*/ Handler target;
/*package*/ Runnable callback;
...
// sometimes we store linked lists of these things/*package*/ Message next;
...
}
boolean enqueueMessage(Message msg, long when) {
...
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
...
// Inserted within the middle of the queue. Usually we don't have to wake// up the event queue unless there is a barrier at the head of the queue// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
...
}
returntrue;
}