2) Looper.loop,进入消息循环


/**
 * Run the message queue in this thread. Be sure to call
 * {@link #quit()} to end the loop.
 */
public static void loop() {
                                                                        
    // 这里的 me 即为所在线程中的存储在本地线程局部变量中的 Looper 对象       
    Looper me = myLooper();
                                                                        
    // 取出 looper 中的消息队列,也就是在 prepare() 中创建的队列
    MessageQueue queue = me.mQueue;
                                                                         
    // Make sure the identity of this thread is that of the local process,
    // and keep track of what that identity token actually is.
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();
                                                                         
    while (true) {
        Message msg = queue.next(); // might block
        if (msg != null) {
            if (msg.target == null) {
                // No target is a magic identifier for the quit message.
                return;
            }
            long wallStart = 0;
            long threadStart = 0;
            ... .. .
            // 实际的消息分派在这里
            // 从第一节的图中可以看到 Message.target 为 Handler
            msg.target.dispatchMessage(msg);
            ... ...
            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }
                                                                                
            msg.recycle();
        }
    }
}
                                                                     
/**
 * Return the Looper object associated with the current thread.  Returns
 * null if the calling thread is not associated with a Looper.
 */
public static Looper myLooper() {
    return sThreadLocal.get();
}


   其实从 Looper 的 prepare 和 loop 两个关键方法已经引出了 Handler, MessageQueue, Message,结合图可以简单的说清他们之间的关系:


   - Looper 创建了 MQ;

   - MQ 使用单链表结构存储了所有 Message;

   - 每个 Message 又会关联一个处理此消息的 Handler;

   - 而这个 Handler 就是最终用来处理此消息的;


   当然,里面也还有很多细节的,我们再从 Looper.loop() 方法中的关键调用 msg.target.dispatchMessage(msg); 的消息分派开始深入了解一下 Handler。


Handler


   我结合自己的问题更深入了解 Handler 的:


   - 从图中可以看到 Handler 中也有一个 mQueue,这个 mQueue 和 Looper 中创建的队列有什么不同么?


   在找这个答案的同时,也正好是了解一下 Handler 的三种构造方式:


/**
 * Default constructor associates this handler with the queue for the
 * current thread.
 *
 * If there isn't one, this handler won't be able to receive messages.
 */
public Handler() {
    ... ...
    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = null;
}
/**
 * Constructor associates this handler with the queue for the
 * current thread and takes a callback interface in which you can handle
 * messages.
 */
public Handler(Callback callback) {
    ... ...
    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }       
    mQueue = mLooper.mQueue;
    mCallback = callback;
}
/**
 * Use the provided queue instead of the default one.
 */
public Handler(Looper looper) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = null;
}


   代码很清晰,这里的 mQueue 其实就是 Handler 对象所在线程的 Looper 的 MQ,两者是同一个 MQ。在第二个构造方式中,又扯入了一个 mCallback 成员,根据名称应该是 消息的回调,下面在分析 dispatch 时会看到;


  - Looper.loop() 中的 queue.next() 的消息来自于哪里,也就是消息怎么入队的?


   最简单的方式应该是通过 Looper.getQueue() 得到 MessageQueue 对象,再通过 MessageQueue 的 enqueueMessage() 方法将消息入队。可惜,不行啊,Looper.getQueue() 为 @Hide 的,上层应用无法访问的。可以通过 Handler 的一些辅助方法来访问:


// 将消息加入 MQ 尾部
public final boolean sendMessage(Message msg)
// 将消息加入 MQ 头部,用于放置优先级较高的消息
public final boolean sendMessageAtFrontOfQueue(Message msg)
// 移除消息码为 what 的消息
public final void removeMessages(int what)
// 创建一个消息码为 what 的消息
public final Message obtainMessage(int what)
// 查看 MQ 中是否有消息码为 what 的消息
public final boolean hasMessages(int what)


   上面只列出了一部分 Handler 提供的消息访问相关的方法,更多的如下图:


094140174.png


   下面为消息入队(sendMessage)的源码过程:


/**
 * Enqueue a message into the message queue after all pending messages
 * before the absolute time (in milliseconds) <var>uptimeMillis</var>.
 * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
 * You will receive it in {@link #handleMessage}, in the thread attached
 * to this handler.
 *
 * @param uptimeMillis The absolute time at which the message should be
 *         delivered, using the
 *         {@link android.os.SystemClock#uptimeMillis} time-base.
 *        
 * @return Returns true if the message was successfully placed in to the
 *         message queue.  Returns false on failure, usually because the
 *         looper processing the message queue is exiting.  Note that a
 *         result of true does not mean the message will be processed -- if
 *         the looper is quit before the delivery time of the message
 *         occurs then the message will be dropped.
 */
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
    boolean sent = false;
    MessageQueue queue = mQueue;
    if (queue != null) {
        // 这里将该消息的 target 设置为本 handler
        msg.target = this;
        sent = queue.enqueueMessage(msg, uptimeMillis);
    }
    ... ...
    return sent;
}


       其中,参数 uptimeMillis 为发送消息时的绝对时间,一般应用都是通过调用 sendMessage(Message msg)方法,而该方法会调用 sendMessage(Message msg, long delayMillis),在该方法中又会设置 uptimeMillis 参数,并调用上面的方法实现。


       这里的主要动作就是设置 Message 的 target 为调用的 Handler,并将消息入队。


   - Handler 的消息分派机制;


public void dispatchMessage(Message msg) {
    // 如果 Message 本身设置了 callback,则交给 Message 自己的 callback
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        // 如果是 Handler 设置了 callback,则交给 handler 的 callback
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
                  
        // 如果都没有设置,则交给 handleMessage
        handleMessage(msg);
    }
}


   可以看到这里的消息分派的机制和流程是:


   首先判断被分派的消息本身是否设置了 callback,如果设置了,则交给该 callback,分派结束;

   如果 Message 没有设置 callback,则判断 Handler 本身有没有设置 callback,如果设置,则交给 Handler 的 callback,分派结束;

   如果 Handler 也没有设置,则调用 Handler.handleMessage(Message),而该 handleMessage 就是应用需要实现的处理消息的地方了。