1.Handler,帝国使命管理者
与每个Message所关联,每条Message都会持有一个Handler,同时负责消息的发送,以及消息的分发。接下来看看Handler源码:
//***************************Handler的构建***************************
//在创建Handler的时候,Looper、MessageQueue同时会出现
//在传入Looper的情况下
public Handler(Looper looper) {
this(looper, null, false);
}
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
//在没有传入Looper情况下
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
//***************************Handler消息发送***************************
//最终是调用的这个私有方法
/**
* @param uptimeMillis 经过计算所获的一个时间戳,对应每条消息
*/
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;//消息持有当前Handler
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//调用MessageQueue的入队方法,将消息入队
return queue.enqueueMessage(msg, uptimeMillis);
}
//***************************Handler消息分发***************************
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//我们一般发送的post消息会走这里,由Message的CallBack回调。也可以发现这里回调的优先级。
handleCallback(msg);
} else {
if (mCallback != null) {
//这是构建Handler传入Callback
if (mCallback.handleMessage(msg)) {
return;
}
}
//如果没有传入Callback,就从重写的handleMessage回调
handleMessage(msg);
}
}
2.MessageQueue,帝国士兵队列
维护当前线程所有的Message,并会对进队的消息按照Message所携带的
when时间戳进行排序。就像是按照身高在排前后顺序一样。Handler里的延时消息就与入队所携带的时间戳有关。
//出队
Message next() {
//*******省略**********
for (;;) {
//*******省略**********
//堵塞线程?
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
//获取一个时间戳
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
//*******省略**********
if (msg != null) {
//判断当前消息是否需要延时
if (now < msg.when) {
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
//返回当前消息
return msg;
}
} else {
//队列为空
nextPollTimeoutMillis = -1;
}
//*******省略**********
}
//*******省略**********
}
}
//Handler会调用这个方法将Message入队
/**
* @param msg Message
* @param when 当前消息所携带的时间戳
*/
boolean enqueueMessage(Message msg, long when) {
//*******省略**********
synchronized (this) {
//*******省略**********
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 {
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;
}
//*******省略**********
}
return true;
}
3.Looper,帝国的将军
通过
ThreadLocal保证了同一线程中自己的唯一性,在自己私有的构造方法中,又保证了自己管理的士兵队列MessageQueue的唯一。当将军开始点兵的时候,源码就来了:
public static void loop() {
//*******省略**********
//当前Looper所关联的MessageQueue
final MessageQueue queue = me.mQueue;
//*******省略**********
//循环查询消息
for (;;) {
//*******省略**********
/**
* 关键的一行,是使用Message所关联的Handler进行分发消息。
* 每个线程有唯一的Looper、MessageQueue管理Message。但是Handler
* 是没有限制的,并且消息和Handler是关联的。
*/
msg.target.dispatchMessage(msg);
//*******省略**********
}
}
//这是Handler中的方法
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//我们一般发送的post消息会走这里,由Message的CallBack回调。也可以发现这里回调的优先级。
handleCallback(msg);
} else {
if (mCallback != null) {
//这是构建Handler传入Callback
if (mCallback.handleMessage(msg)) {
return;
}
}
//如果没有传入Callback,就从重写的handleMessage回调
handleMessage(msg);
}
}
4.Message,帝国的士兵,使命承载者
信息的携带者,有点像个Entity,哈哈~~,查看几个关键的位置:
//甄别消息的标志,士兵的腰牌
public int what;
//所传送的消息内容,士兵的使命内容
public Object obj;
//当前消息关联的时间戳。也是完成使命的时间。这个时间戳获取方式一定要注意
long when;
//当前消息所持有的Handler
Handler target;
//我们在使用postDelayed时候传入的回调,就是他了。
Runnable callback;
//MessageQueue的基础,也像极了士兵的队列
Message next;
5.你们的皇帝回来了(串流程)
-
构建Handler(同时产生Looper、MessageQueue)
-
发送消息:调用
sendMessage(),最终会调用MessageQueue的enqueueMessage()方法入队,这时候会把入队消息进行排序,等待获取。 -
Looper的
loop启动时机有两个- ActivityThread的main方法调用(系统调用)
- 手动进行调用
-
当Looper的循环启动,从MessageQueue中取出适当消息后,就会通过当前消息所关联的Handler进行分发
dispatchMessage()
6.疑惑问答
- Handler的延时消息是如何实现的?
在每一个Message中,都会保存一个相对消息的时间戳(毫秒)when,在Looper循环取消息的时候会进行判断。
- 是一个线程维护一个Looper,一个Looper对应一个MessageQueue?
从源码可以发现,在调用Looper.prepare()时,如果在ThreadLocal中获取Looper不为null,就会抛出异常throw new RuntimeException("Only one Looper may be created per thread")。MessageQueue的初始化又在Looper的构造方法中,所以他们时一一对应的。