public final class Looper {
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
}
public final class Looper {
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
}
Handler原理分析
Handler
的原理分析这个标题,很多文章都写过,最近认真将源码逐行一字一句研究,特此自己也总结一遍。首先是
Handler
整个Android消息机制的简单概括:分三部分对消息机制的整个流程进行阐述:
Handler
的创建,包括Looper
、MessageQueue
的创建;Handler
发送消息,Message
是如何进入消息队列MessageQueue
的(入列);Looper
轮询消息,Message
出列,Handler
处理消息。一、Handler创建流程分析
1.Handler如何被创建的
首先,如何避免
Handler
的内存泄漏是一个非常常见的面试题,其实Handler
的源码中已经将答案非常清晰告知给了开发者,即让Handler
的导出类保证为static
的,如果需要,将Context
作为弱引用的依赖注入进来。同时,在
Handler
创建的同时,会尝试获取当前线程唯一的Looper
对象:关于
ThreadLocal
,我在上一篇文章中已经进行了分析,现在我们知道了ThreadLocal
保证了当前线程内有且仅有唯一的一个Looper
。2.Looper是如何保证线程单例的
那就是需要调用
Looper.prepare()
方法:这也就说明了,为什么当前线程没有
Looper
的实例时,会抛出一个异常并提示开发者需要调用Looper.prepare()
方法了。也正如上述代码片段所描述的,如果当前线程已经有了
Looper
的实例,也会抛出一个异常,提示用户每个线程只能有一个Looper
(throw new RuntimeException("Only one Looper may be created per thread");
)。此外,在
Looper
实例化的同时,也创建了对应的MessageQueue
,这也就说明,一个线程有且仅有一个Looper
,也仅有一个MessageQueue
。二、发送消息流程分析
1.sendMessage()分析
sendMessage()
流程如下:注意第四步实际上将
Handler
对象最为target,附着在了Message
之上;接下来看MessageQueue
类内部是如何对Message
进行入列的。2.MessageQueue消息入列
MessageQueue
的数据结构本身是一个单向链表。三、接收消息分析
当
Handler
创建好后,若在此之前调用了Looper.prepare()
初始化Looper
,还需要调用Looper.loop()
开始该线程内的消息轮询。1.Looper.loop()
比较简单,需要注意的一点是
MessageQueue.next()
是一个可能会阻塞线程的方法,当有消息时会轮询处理消息,但如果消息队列中没有消息,则会阻塞线程。2.MessageQueue.next()
注意代码片段最上方的native方法——循环体内首先调用
nativePollOnce(ptr, nextPollTimeoutMillis)
,这是一个native方法,实际作用就是通过Native层的MessageQueue
阻塞nextPollTimeoutMillis
毫秒的时间:搞清楚这一点,其它就都好理解了。
3.最终将消息发送给Handler
正如上文所说的,
msg.target.dispatchMessage(msg)
实际上就是调用Handler.dispatchMessage(msg)
,内部最终也是执行了Handler.handleMessage()
回调:参考&感谢
关于我
Hello,我是却把清梅嗅,如果您觉得文章对您有价值,欢迎 ❤️,也欢迎关注我的博客或者Github。
如果您觉得文章还差了那么点东西,也请通过关注督促我写出更好的文章——万一哪天我进步了呢?