Handler Looper( 五 )


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 {...}
有人可能会好奇这个when怎么会为0呢,这里提一嘴,除了有正常的之流的方法还有一个比较特殊的方法:
public final boolean sendMessageAtFrontOfQueue(Message msg) {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, 0);}
这个方法特殊在什么地方呢,打个比方,如果说我们正常的之流的方法是一群正常排队的人,按照来的时间先后有序排队,但是Queue就是那种个别不老实的,它能直接插队到最前面,然后他传递的为0,这也是唯一一个特殊的发送消息的方法 。
这个判断语句成立的条件有三点:p == null || when == 0 || when < p.when
综合来说就是,如果这时候新进来一个消息,这时候消息队列里面没有需要执行的消息,或者新进来的这个消息是通过Queue( msg)方法传进来的,或者说新进来的这个消息需要等待的时间比之前在等待的消息等待的时间短,那么就把这个消息插入链表的表头,此时系统会唤醒这个消息队列无论队列是否堵塞 。
// Got a message.mBlocked = false;
这一行代码说明只要消息队列有消息,这个队列就不阻塞,然后把这个布尔值传递:
【Handler Looper】boolean needWakeneedWake = mBlocked;
那么这一块代码就打通了,下面这块else语句块:
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.nextprev.next = msg;}
讲的是如何把消息插入链表的内部,这时候就不需要去调整唤醒消息队列的时间,因为唤醒的时间是跟表头有关的,这样整个入队的操作差不多就过了一遍.
出队操作
既然有入队操作那么肯定也有出队操作,如果你还记得我们最开始使用的类的话,那么这里不妨直接告诉你,出队的方法就在类里面,这里有个loop()方法:
/*** Run the message queue in this thread. Be sure to call* {@link #quit()} to end the loop.*/public static void loop() {final Looper me = myLooper();if (me == null) {throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");}final MessageQueue queue = me.mQueue;// Make sure the identity of this thread is that of the local process,// and keep track of what that identity token actually is.Binder.clearCallingIdentity();final long ident = Binder.clearCallingIdentity();//死循环for (;;) {//把消息从队列取出Message msg = queue.next(); // might blockif (msg == null) {// No message indicates that the message queue is quitting.return;}// This must be in a local variable, in case a UI event sets the loggerfinal Printer logging = me.mLogging;if (logging != null) {logging.println(">>>>> Dispatching to " + msg.target + " " +msg.callback + ": " + msg.what);}final long traceTag = me.mTraceTag;if (traceTag != 0) {Trace.traceBegin(traceTag, msg.target.getTraceName(msg));}try {msg.target.dispatchMessage(msg);} finally {if (traceTag != 0) {Trace.traceEnd(traceTag);}}if (logging != null) {logging.println("