在日常开发中我们经常用到Handler,用来处理、传递消息而Handler中内部怎么实现,它与Looper、MessageQueue到底有什么关系确说不上来。
先看下大体流程图:
MessageQueue内部维护了一个Message的队列,我们通过Handler将消息Message发送到Looper中的MessageQueue,通过不断循环的Looper从MessageQueue中取出消息进行分发与执行。下面我们通过源码具体分析:
//不传参数构造方法
Handler handler = new Handler();
最后会调用Handler中的这个构造方法
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
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;
}
在此构造方法主要对Handler 中的mLooper与mQueue赋值。
mLooper = Looper.myLooper(); 获取的是当前线程的Looper
mQueue获取的是Looper中的 MessageQueue。
Handler发送消息
handler.sendMessage()
最后会调用Handler中
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
在Handler中的enqueueMessage调用了MessageQueue中的enqueueMessage
boolean enqueueMessage(Message msg, long when) {
省略......
synchronized (this) {
if (mQuitting) {
//线程退出 回收消息
msg.recycle();
return false;
}
//标记消息为再用状态
msg.markInUse();
//设置等待时长
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
这里主要将Message添加入队列
最后在当前线程中Looper.loop()中处理Message
public static void loop() {
final Looper me = myLooper();
......
for (;;) {
Message msg = queue.next(); // might block
......
try {
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
......
}
}
最后会调用msg.target.dispatchMessage(msg)分发消息,msg.target是传入的是Handler,所以最后会调用Handler的dispatchMessage方法分发。
再说下Looper的启动,在我们的主线程UI线程中,Looper是由ActivityThread启动,我们在看下ActivityThread的main()方法
/frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
.....
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
......
Looper.loop();
......
}
我们可以看到在ActivityThread的main方法中实例化了ActivityThread,并且在主线程中调用Looper.prepareMainLooper();
最后调用了Looper的prepare 方法
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));
}
在此方法为sThreadLocal 赋值实例化的Looper,在ActivityThread中最后调用Looper.loop(); 循环处理消息。
从ActivityThread的main函数中可得知,如果在子线程使用Handler需要调用Looper.prepare() 后调用Looper.loop()才可以传递处理Message