以前面试面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;
}