..
}
prepareMainLooper()
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
sMainLooper
只能被初始化一次,也就是说 prepareMainLooper()
只能调用一次,否则将直接抛出异常。
prepare()
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
// 每个线程只能执行一次 prepare(),否则会直接抛出异常
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 将 Looper 存入 ThreadLocal
sThreadLocal.set(new Looper(quitAllowed));
}
主线程中调用的是 prepare(false)
,说明主线程 Looper 是不允许退出的。因为主线程需要源源不断的处理各种事件,一旦退出,系统也就瘫痪了。而我们在子线程调用 prepare()
来初始化 Looper时,默认调动的是 prepare(true)
,子线程 Looper 是允许退出的。
每个线程的 Looper 是通过 ThreadLocal
来存储的,保证其线程私有。
再回到文章开头介绍的 Handler 的构造函数中 mLooper
变量的初始化:
mLooper = Looper.myLooper();
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
也是通过当前线程的 ThreadLocal
来获取的。
构造函数
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed); // 创建 MessageQueue
mThread = Thread.currentThread(); // 当前线程
}
再对照 Handler 的构造函数:
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
其中的关系就很清晰了。
Looper
持有 MessageQueue
对象的引用
Handler
持有 Looper
对象的引用以及 Looper
对象的 MessageQueue
的引用
loop()
看到这里,消息队列还没有真正的运转起来。我们先来看一个子线程使用 Handler 的标准写法:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
让消息队列转起来的核心就是 Looper.loop()
。
public static void loop() {
final Looper me = myLooper(); // 从 ThreadLocal 中获取当前线程的 Looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue; // 获取当前线程的消息队列
... // 省略部分代码
for (;;) { // 循环取出消息,没有消息的时候可能会阻塞
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
... // 省略部分代码
try {
msg.target.dispatchMessage(msg); // 通过 Handler 分发 Message
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
... // 省略部分代码
msg.recycleUnchecked(); // 将消息放入消息池,以便重复利用
}
}
简单说就是一个死循环不停的从 MessageQueue 中取消息,取到消息就通过 Handler 来进行分发,分发之后回收消息进入消息池,以便重复利用。
从消息队列中取消息调用的是 MessageQueue.next()
方法,之前已经分析过。在没有消息的时候可能会阻塞,避免死循环消耗 CPU。
取出消息之后进行分发调用的是 msg.target.dispatchMessage(msg)
,msg.target
是 Handler 对象,最后再来看看 Handler 是如何分发消息的。
public void dispatchMessage(Message msg) {
if (msg.callback != null) { // callback 是 Runnable 类型,通过 post 方法发送
handleCallback(msg);
} else {
if (mCallback != null) { // Handler 的 mCallback参数 不为空时,进入此分支
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg); // Handler 子类实现的 handleMessage 逻辑
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
- Message 的 callback 属性不为空时,说明消息是通过
postXXX()
发送的,直接执行 Runnable 即可。
- Handler 的 mCallback 属性不为空,说明构造函数中传入了 Callback 实现,调用
mCallback.handleMessage(msg)
来处理消息
- 以上条件均不满足,只可能是 Handler 子类重写了
handleMessag