在Android面试的过程中,Handler机制是一个必问的问题,而其中的源码更是面试官喜欢用来当做面试题考察面试者分析源码的能力。(我深受其害啊!所以痛下决心花了一段时间搞定他)
Handler主要涉及到Handler,Looper,ThreadLocal,MessageQueue和Message。以下是自己的理解加上源码的分析做出的一些总结,不对之还请指正。
1.涉及主要的五个对象
Looper:扮演消息循环的角色,持有MessageQueue对象
ThreadLocal:用于保存looper对象,looper对象持有MessageQueue
Handler:操作Message消息的类
MessageQueue:消息队列,保存要传递的消息msg的对象
Message: 消息对象,保存要传递的信息和handler对象
2.Handler的执行过程
先给出一张自己动手画好的图:
1).ActivityThread:
在Activity中,会创建ActivityThread线程,也就是我们说的主线程,在这个线程中,调用Looper.perpare()方法;
2).Looper.prepare():
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));
}
1.创建Looper对象,其实在looper对象中创建了MessageQueue消息队列对象
2.将looper对象通过set方法保存在ThreadLocal当中,其中的looper持有了MessageQueue的对象
3).mHandler.sendMessage(Message msg);
本质上会调用sendMessageAtTime(),其实post方法也是调用这个方法。
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
而在enqueueMessage()方法中
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
本质上就是将msg添加到queue中,也就是说,sendMessage()方法最终的目的是将Mssage对象添加到MessageQueue消息队列中。
这个是子线程中发送消息时候调用的。
4).Looper.loop()
源码如下,省略了一些个人觉得非重点的部分
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;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final long traceTag = me.mTraceTag;
if (traceTag != 0) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
.....
}
1.第二行,调用Looper的静态方法myLooper(),本质上是取出ThreadLocal中的保存的Looper对象,这样就保证整个体系中只有一个Looper对象;
final Looper me = myLooper();
2.for是一个死循环,调用取出的Looper对象中的Message里面的next()方法,不断的接收从子线程的handler发送过来的消息,而next()是一个阻塞方法,没有消息的时候停在这里,只有子线程调用sendMessageAtTime()方法后才能往下执行;
Message msg = queue.next(); // might block
3.next()方法执行后得到Message对象,调用Handler的dispatchMessage方法,实际上就是try里面的这句
msg.target.dispatchMessage(msg);
这个方法会调用我们在创建Handler对象时重写的handleMessage方法,handlerMessage就得到了Message,我们这样就取出了子线程的msg,整个过程就已经完成。