03. Looper源码分析
03. Looper源码分析
Looper类说明
用于为线程运行消息循环的类。 默认情况下,线程没有与之关联的消息循环; 要创建一个,请在要运行循环的线程中调用 {@link #prepare},然后 {@link #loop} 让它处理消息,直到循环停止。 <p>
与消息循环的大多数交互是通过 {@link Handler} 类进行的。 <p>
这是一个Looper线程实现的典型例子,利用{@link #prepare}和{@link #loop}的分离来创建一个初始的Handler来与Looper进行通信。
API 实现说明
此类包含设置和管理基于 MessageQueue 的事件循环所需的代码。 影响队列状态的 API 应该在 MessageQueue 或 Handler 上定义,而不是在 Looper 本身上定义。 例如,空闲处理程序线程、循环和退出是在循环器上定义的。
属性
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper; // guarded by Looper.class
private static Observer sObserver;
final MessageQueue mQueue;
final Thread mThread;
sThreadLocal
Looper数据与线程绑定,每个线程下对应一个Looper。
sMainLooper
初始化调用链
// MainLooper由Android环境创建,不用手动调用这个函数。 prepareMainLooper()已弃用 <-- myLooper() <-- sThreadLocal.get()
使用getMainLooper()可直接获取MainLoopr引用
ThreadLocal是什么时候set looper的?
//将当前线程初始化为looper。 这使您有机会创建处理程序,然后在实际开始循环之前引用此循环器。 请务必在调用此方法后调用 {@link #loop()},并通过调用 {@link #quit()} 结束它。
prepare(boolean quitAllowed) <-- prepare()
prepare实际上是将当前Looper绑定在所在线程上。 或者说 创建与当前线程相关的Looper.
注释中提到在调用此方法后调用loop(), 为什么?
调用此方法循环处理MessageQueue中的消息. 怎么做的?
loop()
final Looper me = myLooper(); //获取当前线程looper
for (;;) {
if (!loopOnce(me, ident, thresholdOverride)) {
return;
}
}
* 轮询并传递单个消息,如果外部循环应该继续,则返回 true。
private static boolean loopOnce(final Looper me,
final long ident, final int thresholdOverride) 方法
//循环从MessageQueue中获取Message,读取完毕,不再有数据,返回false,loop()方法跳出
Message msg = me.mQueue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return false;
}
...
msg.target.dispatchMessage(msg); //调用Handler.dispatchMessage
...
//回收message对象
msg.recycleUnchecked();
调用quit()结束looper, 是如何实现的?
??
阶段总结
Message 链表结构数据类 可以使用obtain()创建和复用Message对象。 Looper创建ThreadLocal<Looper>
存储与线程关联的Looper实例。 在Looper.prepare()中创建,并使用ThreadLocal.set。
Looper.loop() 循环调用MessageQueue中的next方法。全部取出后跳出方法。 每次取出Message对象时都会回收至对象池。