以前面试面Android的消息机制,只知道回答Looper的创建是怎么创建的?MessageQueue是和ThreadLocal相关联的,Looper是死循环不断的取出消息就OK了。大概相关的知识点如下:

  • 每个Handler都会关联一个消息队列,消息队列被封装在Looper中,而每个Looper又会关联一个线程(存放在ThreadLocal中),最终就等于每个消息队列关联一个线程。Handler相当于处理这个消息队列的消息处理器,即使你创建再多的handler,他发消息都会发到同一个消息队列中去,只不过是哪个Handler发的,消息队列会让哪个Handler来处理

  • Handler创建的时候是如何关联Looper的?当在主线程中创建Handler的时候,因为主线程(UI线程)启动的时候已经初始化好了一个Looper(消息队列),所以可以直接创建,并自动将创建好的线程唯一的消息队列关联给Handler如果在一个子线程中直接创建Handler的话,因为没有创建属于该线程的消息队列,因此Handler会创建失败,解决的方法是在子线程中创建一个消息队列,并让消息队列循环起来以后在进行创建Handler

  • Looper对象存放在哪里? Looper对象是每个线程所持有的唯一的一个消息队列,存在在该线程的一个静态的ThreadLocal变量中,关于ThreadLocal的理解可以看ThreadLocal的理解。在主线程中在app一启动的时候系统就已经为UI线程创建好了一个Looper并存在了ThreadLocal中,并让这个Looper开始循环起来

  • Handler为何能处理消息?Looper建立以后就会立即执行loop方法,他是一个死循环,不断的取消息Message中有一个Handler的变量名为target,如果target不是空,那么就会调用Message中target的dispatchMessage分发到Handler,由Handler来处理这个消息,这也解释了为什么是同一个消息队列不同的Handler post的消息只能自己执行,就是因为每个消息都有一个target来指明了谁发送的自己就会由谁来处理自己。

    ok,后来面试的时候遇到一个更细的点,那就是sendMessageDelay这种是怎么实现的?如果保证消息的延时发送的?后来去看了看Looper#loop()方法的代码才明白,下边是记录:
    先看一下MessageQueue#enqueueMessage()方法的伪码:

boolean enqueueMessage(Message msg, long when) {
        //...省略一些判空逻辑..
        synchronized (this) {
            //...省略线程判断逻辑...
            msg.when = when;
            //mMessages是当前消息链表的一个头指针
            Message p = mMessages;

            /**
             * 如果入队的消息的时间是0或者时间早于头指针的消息,
             * 就把入队的消息放到前边成为新的头指针
             */
            if (p == null || when == 0 || when < p.when) {
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                //否则就去消息队列中一个一个判断,根据时间放在合适的位置
                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;
            }
            //...省略部分代码
        }
        return true;
    }