基于8.0.0源码
##定义##
/**
* Low-level class holding the list of messages to be dispatched by a
* {@link Looper}. Messages are not added directly to a MessageQueue,
* but rather through {@link Handler} objects associated with the Looper.
*
* <p>You can retrieve the MessageQueue for the current thread with
* {@link Looper#myQueue() Looper.myQueue()}.
*/
个人理解
-
MessageQueue是一个内部维护一个消息列表,并通过Looper来派发Message的类. Messages并不是直接添加到MessageQueue里,而是通过和Looper有关系的Hander来添加的.
-
我们可以在当前线程通过Looper.myQueue()来获取当前线程的MessageQueue.
方法细节
MessageQueue类
- final class MessageQueue
- 可以看到MessageQueue是被final修饰的类,那么我们知道final修饰类的特点: final类不能被继承,也没有子类,内部方法默认也是final修饰.
- Google处于安全考虑,把MessageQueue定义成了final类.
构造方法
MessageQueue(boolean quitAllowed) {
//赋值给类变量mQuitAllowed,类变量指如果MessageQueue可以退出的话那么这个变量就为true
mQuitAllowed = quitAllowed;
//掉用nativeInit()方法,返回的是一个long类型,暂时不谈论Native层方法
mPtr = nativeInit(); //初始化方法
}
- 系统提供了一个有参的构造来创建MessageQueue, quitAllowed意思是指是否可以手动退出.MessageQueue是依附于Looper的.Android中规定UI线程中是不可以手动退出MessageQueue的,因为UI线程(主线程)避免误操作.而其他工作线程是可以手动退出MessageQueue.
消息入队enqueueMessage方法
源码分析:
boolean enqueueMessage(Message msg, long when) {
//如果msg的target对象也就是宿主Handler的对象为空,就抛出异常
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
//如果msg的状态是in-use状态,就抛出异常
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
//如果当前MessageQueue已经退出,就抛出异常
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的状态置为in-user,when属性赋值,
msg.markInUse();
msg.when = when;
//拿到msg队列头
Message p = mMessages;
//是否需要唤醒线程
boolean needWake;
//当队列等于空,when的时间等于0,传入的when比队列头的when时间小的时候
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
//插入到头部,赋值,如果线程block则唤醒
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.
//线程堵塞或者msg的宿主Handler对象为空,msg是异步操作的时候
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;
}
// We can assume mPtr != 0 because mQuitting is false.
//是否需要唤醒线程
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
消息入队总结:
-
- 先校验msg的宿主Handler是否存活,msg的状态是被使用,MessageQueue是否已经退出.
-
- 满足队列为空,处理时间等于0,传入的when比队列头的when要小的时候, 插入到队列的头优先处理.
-
- 以上情况都不满足的时候,从头遍历队列根据被处理时间找到它的位置.
消息出队 next方法
源码分析:
Message next() {
// Return here if the message loop has already quit and been disposed.
// This can happen if the application tries to restart a looper after quit
// which is not supported.
//mPtr是Native层返回的NativeMessageQueue的地址,在构造方法中初始化得到值. 如果等于0就说明队列不存在或者被清空了.
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
//第一次初始化的时候为 -1,待处理的IdleHandler数量
int pendingIdleHandlerCount = -1; // -1 only during first iteration
//线程阻塞的时间, -1 表示一致阻塞, 0 表示不阻塞, > 0 表示阻塞 nextPollTimeoutMillis长时间
int nextPollTimeoutMillis = 0;
for (;;) {
//死循环,代码省略
//对消息出队做处理
...
}
// Reset the idle handler count to 0 so we do not run them again.
//把idleHandler的数量置为 0
pendingIdleHandlerCount = 0;
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
//线程状态置为不阻塞
nextPollTimeoutMillis = 0;
}
}