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 提供的消息访问相关的方法,更多的如下图:



下面为消息入队(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 就是应用需要实现的处理消息的地方了。



更多相关文章

  1. android 一个应用去获取另一个应用assets下面的资源通过框架代码
  2. Android应用程序键盘(Keyboard)消息处理机制分析(6)
  3. 【Android】getColor(int id)在API23时过时
  4. MTK Android(安卓)如何自动挂断电话
  5. Android(安卓)5.0 API变化
  6. android 退出全部activity的方法
  7. getReadableDatabase() 和 getWritableDatabase()
  8. Android中Log机制
  9. android ListView本行控件操作本行其它控件的重要方法(绝对原创,本

随机推荐

  1. Runtime.exec 执行命令行
  2. Android(安卓)Accessibility : TalkBack
  3. 安卓指定横竖屏失效问题修复
  4. 图片处理
  5. Security and Permissions 安全与权限 (一
  6. Android(安卓)Studio通过style和layer-li
  7. android的fragment使用中static静态fragm
  8. Android自定义系统分享面板
  9. Android(安卓)Java(2015-6-18 15:28、2016
  10. 软键盘问题汇总