Handler 调用MessageQueue
- 将Runnable对象封装到Message中。
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
- 将延迟时间统一到未来时间点
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
- 检查MessageQueue是否已经初始化,即线程是否已经启动。
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);
}
- 将消息插入到队列中,调用MessageQueue方法接口enqueueMessage。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
MessageQueue 将消息归入队列
boolean enqueueMessage(Message msg, long when) {
...
//为什么要使用synchronized关键字来同步?
//因为我们的Handler对象可以被其他线程引用
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
//如果消息当前没有消息,或者消息msg要立即执行,或者msg的触发时间点
//早于已有消息的时间,则本msg为队列头。
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {//貌似无限循环
prev = p;
p = p.next;//p循环向后移动
if (p == null || when < p.when) {
break;//如果p是最后一个节点,或者当前msg的触发时间早于p的时间
//则此处为msg的插入位置
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
//插入msg.
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);//唤醒线程,要求其取出消息,并调用消息的Handler的dispatchMessage方法
}
}
return true;
}
Message消息创建
上面我们未深入方法getPostMessage( r ) 方法,现在我们看看。
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();//直接调用类方法obtain,而不是直接调用构造方法
m.callback = r;//Runnable更新
return m;
}
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
* 意思是优先使用消息池中的消息对象,消息池size为50
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {//消息池不为空
Message m = sPool;
sPool = m.next;//消息池向下一个空消息移动
m.next = null;//退出空消息池队列
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;//返回消息
}
}
return new Message();//没有消息,则直接新建消息对象
}
那么空消息池是怎么创建的呢?
/**
* Recycles a Message that may be in-use.
* Used internally by the MessageQueue and Looper when disposing of queued Messages.
*/
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;//将消息所有属性全部清空
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {//如果消息池未满
next = sPool;//将消息归入队列中
sPool = this;
sPoolSize++;
}
}
}
结语
- MessageQueue并不是一个数据结构queue,而是Message对象的一个管理接口
- Handler不直接管理Message
- Message创建优先使用消息池中已有对象,Message是直接继承Parcelable,所以Message可以进程通信
- 线程唤醒是调用Looper的wake方法。
mLooper->wake();
- Message可以理解为一只托盘,你的任务在盘里,线程取出盘子来吃你的任务。
- 当前没有任务时(或任务时间没有到),则线程暂停。