我们要在Android中使用Handler机制,必须要经过如下三个过程:
下面我们从源码的角度去查看为什么要经过这三个过程Handler机制才能正常工作:
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));
}
从源码中发现,在Handler机制中的 MessageQueue 是由 Lopper 来维护的, 为什么? 因为源码中有这么一段:
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
所以经过源码中的步骤,一个线程就和一个 Lopper 关联起来了,而这个 Lopper 又维护着一个 MessageQueue .
public Handler(Callback callback, boolean async) {
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
这是 Lopper.myLopper 的源码:
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
所以通过这一步我们看到, 源码帮我们把 我们之前调用的 Looper.prepare 创建的 looper 对象和一个 Handlder 关联起来了,并且Handler 还获取了由 Looper 维护的 MessageQueue! 接下来就可以干大事了!!!
public static void loop() {
final Looper me = myLooper();
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);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
}
这里是 Message 类的部分源码,方便理解上面的代码:
class Message implements Parcelable {
Handler target;
}
到了这里,有读者肯定会问,这个 Message 中的 Target 是怎么来的呢, 这个 Message 是如何和一个 Handler 关联起来的呢?
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
首先注意这一段代码是 Handler 中的源码 ,看方法名字就知道,是往之前获取的 MessageQueue中插入消息, 然后最重要的就是
msg.target = this 这句, 通过这句话,这个 Message 就和这个Handler关联起来了,然后在 loop 中就会把这个 message 发送给这个 handler 进行处理!!!
这里顺便说一下为什么在子线程中创建一个 Handler 而没有调用 Looper.prepare 会报错的原因,其实很简单,就是源码中的一段:
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}