MessageQueen是用来存放消息的,我们具体来看一下MessageQueen的运行机制。
具体描述如下:
Low level class holding the list of messages to be dispatched by a Looper. Messages are not added directly to a MessagreQueen,but rather throw MessageQueen.IdleHandler objects associated with Looper .you can retrieve the MessageQueen for the current thread with Looper.myQueen.
通过上述描述可知,MessageQueen是一个保存消息的低级类,其消息由Looper派发。消息并不是直接添加到MessageQueen当中的,而是通过与Looper对象关联的IdleHandler()添加的。通过调用Looper.myQueen可以获得当前消息所在的队列。
MessageQueen的成员变量有以下几个
Message mMessages;
private final ArrayList<IdleHanlder> mIdleHandlers = new ArrayList<IdleHanlder>();
private IdleHanlder[] mPendingIdleHandlers;
private boolean mQuiting;
boolean mQuitAllowed = true;
private boolean mBlocked;
private int mPtr;
private native void nativeInit();
private native void nativeDestroy();
private native void nativePollOnce(int ptr,int timeoutMillis);
private native void nativeWake(int ptr);
各个成员变量含义如下:
Message mMessage:一个Message实例,代表消息队列的头Head。
ArrayList<IdleHandler>:存放IdleHandler的数组。
mQuiting:表示当前队列是否处于正在退出的状态。
mQuitAllowed:表示当前队列是否允许退出。
mBlocked:判读队列是否阻塞等待一个非零超时的pollOnce。
mPtr:指向C/C++的指针,主要操作native函数。
上文提到了,Message并不是直接添加到MessageQueen中的,而是通过IdleHandler()接口添加的,那么我们看一下IdleHandler接口的定义
public static interface IdleHandler{
/**
* Called when the message queue has run out of messages and will now
* wait for more. Return true to keep your idle handler active, false
* to have it removed. This may be called if there are still messages
* pending in the queue, but they are all scheduled to be dispatched
* after the current time
*/
boolean queueIdle();
}
/**
* Add a new IdleHandler to this message queue. This may be
* removed automatically for you by returning false from
* IdleHandler queueIdle IdleHandler.queueIdle() when it is
* invoked, or explicitly removing it with removeIdleHandler.
*/
public void addIdleHandler(IdleHandler handler){
if(handler == null){
throw new NullPointerException("Can't add a null IdleHandler");
}
synchronized(this){
mIdleHandler.add(handler);
}
}
/**
* Remove an IdleHandler from the queue that was previously added
* with addIdleHandler. If the given object is not currently
* in the idle list, nothing is done.
*/
public void removeIdleHandler(IdleHandler handler){
synchronized(this){
mIdleHandler.remove(handler);
}
}
当消息队列为空的时候调用IdleHandler接口,并且等待更多的消息。如果返回值为true,则保持当前IdleHandler是活跃的,否则移除当前IdleHandler。如果当前消息队列里面扔有消息,那么在消息执行完之后仍然会调用该接口。
通过addIdleHandler想MessageQueen添加一个IdleHandler,如果调用IdleHandler.queueIdle(),且返回值为false的时候,系统将自动移除该IdleHandler,或者直接调用removeIdleHandler来进行移除。这个方法是线程安全的。
看一个例子
final class myIdle implements MessageQueue.IdleHandler{
@Override
public final boolean queueIdle(){
doSomething();
return false;
}
}
当MessageQueen中没有任何消息时,就会执行doSomething(),返回值为false,说明不保留该IdleHandler成员。
MessageQueen的构造方法(在Looper中调用)
MessageQueue(boolean quitAllowed){
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
MessageQueen的核心方法 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.
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled.
if (mQuitting) {
dispose();
return null;
}
// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// Reset the idle handler count to 0 so we do not run them again.
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;
}
}
简单的说,这个函数就是从从头Head取出下一个Message,如果队列中没有message了,那么则可以取处理IdleHandler接口。当队列中没有消息或者消息指定了等待时间,那么线程会进入等待状态。
函数中有两个变量
int pendingIdleHandlerCount = -1;空闲的IdleHandler个数,只有在第一次迭代的时候为-1。
int nextPollTimeoutMillis = 0;下一轮等待时间,如果当前消息队列中没哟消息,需要等待的时间。
如果等待时间不为零,执行flush pending command,刷新等待时间。然后执行nativePollOnce(ptr, nextPollTimeoutMillis);其功能是查询消息队列中有没有消息。如果消息为空,那么nextPollTimeoutMillis=-1,接着等待消息,如果不为空,那么就处理这个消息。当我们设置的等待时间到了,将msg从Message中取出来并返回msg,如果没有返回,则说明没有消息需要处理,既然没有消息需要处理,检查以下是否要退出队列,如果退出返回null,否则那么就可以处理IdleHandler,处理完IdleHandler后将nextPollTimeoutMillis设为0(因为在处理IdleHandler的时候可能来消息),重新检测消息。
插入操作
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
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) {
// 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;
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正在使用或者msg对应的Handler为空或者不予许退出,则报异常。如果正在退出,则不允许进行插入操作,否则报异常。正常的插入操作类似于链表。当when=0或者when<p.when时插入表头。
删除
void removeMessages(Handler h, int what, Object object) {
if (h == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
while (p != null && p.target == h && p.what == what
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && n.what == what
&& (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
p = n;
}
}
}
void removeMessages(Handler h, Runnable r, Object object) {
if (h == null || r == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
while (p != null && p.target == h && p.callback == r
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && n.callback == r
&& (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
p = n;
}
}
}
void removeCallbacksAndMessages(Handler h, Object object) {
if (h == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
while (p != null && p.target == h
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
p = n;
}
}
}
quit()方法
void quit(boolean safe) {
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) {
return;
}
mQuitting = true;
if (safe) {
removeAllFutureMessagesLocked();
} else {
removeAllMessagesLocked();
}
// We can assume mPtr != 0 because mQuitting was previously false.
nativeWake(mPtr);
}
}