Looper分析
在 Handler 机制中,Looper
的作用是提供了一个消息循环 ( message loop ) 的机制,用于处理和分发消息。
Looper
是一个线程局部的对象,每个线程只能有一个 Looper
对象 。它通过一个无限循环来不断地从消息队列中取出消息,并将消息分发给对应的 Handler
进行处理。
在使用 Handler 机制时,我们可以通过调用 Looper.prepare()
方法来创建一个Looper对象,并通过 Looper.loop()
方法来启动消息循环。在消息循环开始后,Looper会不断地从消息队列中取出消息,然后将消息分发给对应的 Handler
进行处理。
Handler
可以通过调用 post()
、sendMessage()
等方法将消息发送到消息队列中,然后由 Looper
负责将这些消息取出并分发给对应的 Handler
进行处理。这样就实现了线程间的消息传递和处理。
Looper还可以通过调用 quit()
方法来终止消息循环,停止消息的处理。
下来以主线程内的 Looper
分析下。
Looper 创建/运行
App 运行,进程创建后主线程开始运行的入口在 ActivityThread
的 main(String[] args)
方法。
java
// ActivityThread.java sdk30
public static void main(String[] args) {
// ...... 一系列的初始化操作。
// 创建主线程的 Looper 并设置到 ThreadLocal,同时创建了绑定的 MessageQueue。
Looper.prepareMainLooper();
// ......
ActivityThread thread = new ActivityThread(); // 主线程对象创建
thread.attach(false, startSeq);
if (sMainThreadHandler == null) { // 主线程处理各事件的 Handler
sMainThreadHandler = thread.getHandler();
}
// ......
Looper.loop(); // Looper 开始无限循环,从 MessageQueue 中取消息,也同时保证了主线程的存活。
throw new RuntimeException("Main thread loop unexpectedly exited");
}
上面代码中 Looper
的创建与运行就两行。
-
Looper.prepareMainLooper();
方法的调用,创建了 **主线程 ** 的Looper
对象,并将它设置到了sThreadLocal
中。java// Looper.java sdk30 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)); } @Deprecated public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }
上面代码保证了一个线程只能有一个
Looper
对象:if (sThreadLocal.get() != null)
判断表明sThreadLocal
内对应于主线程的Looper
对象只能存在一个。若主线程运行起来时发现已经有存在的Looper
对象,将抛出异常,也就表明 app 进程直接crash。prepareMainLooper()
被标注了@Deprecated
,Looper
是public
类,在 app 程序中是可以调用Looper.prepareMainLooper()
方法的。换言之,在sThreadLocal
中已经存在Looper
对象的情况下,,可以再次调用方法Looper.prepareMainLooper()
,因此在prepare(boolean quitAllowed)
一开始就先判断是否存在了Looper
对象。进一步表明,一个线程中只能有一个Looper
。- 赋值
sMainLooper
。
这样主线程的
Looper
就创建完成了。 -
Looper.loop();
开启了Looper
的无限循环,从MessageQueue
中取消息,附带同时保证了主线程的存活。还负责将msg
分发给对应的Handler
执行。