上午,刚刚粗略的看完了handler的源码,与其相关类looper类和MessageQueue类也一并看下。
先来看Messagequeue,首先是类介绍:
- Low-level class holding the list of messages to be dispatched by a Looper. Messages are not added directly to a MessageQueue, but rather through MessageQueue.IdleHandler objects associated with the Looper.
- You can retrieve the MessageQueue for the current thread with Looper.myQueue().
保存消息列表的低级别类,消息由 Looper 对象派发。消息并不是直接添加到 MessageQueue 中的,而是通过与 Looper 对象关联的 MessageQueue.IdleHandler 对象添加。
调用Looper.myQueue方法可以获取当前线程的MessageQueue。
再来看一下类中的变量:
- Message mMessages;
- private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
- private IdleHandler[] mPendingIdleHandlers;
- private boolean mQuiting;
- boolean mQuitAllowed = true;
- // Indicates whether next() is blocked waiting in pollOnce() with a non-zero timeout.
- private boolean mBlocked;
- @SuppressWarnings("unused")
- private int mPtr; // used by native code
- private native void nativeInit();
- private native void nativeDestroy();
- private native void nativePollOnce(int ptr, int timeoutMillis);
- private native void nativeWake(int ptr);
- Message的实例
- 存放IdleHandler对象的一个ArrayList
- 一个IdleHandler数组
- 一个boolean值,判断Thread是否退出
- 一个boolean值,判断是否允许退出
- 一个boolean值,判断next()是否阻塞等待一个非零超时的pollOnce()
- 下面的就是native code了。本文不做详解。
前面提到Message不是直接添加到MessageQueue里的,是通过IdleHandler接口进行Message添加,所以先看下IdleHandler:
- /**
- * Callback interface for discovering when a thread is going to block
- * waiting for more messages.
- */
- 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();
- }
一个用于在一个线程为了等待更多消息阻塞时的接口。当消息队列为空,等待更多消息时, 执行这个queueIdle函数,如果返回真,继续保持你的idlehandler的活跃状态,如果返回值为false,那么就会从应用程序中移除这个IdleHandler,否则的话就会在应用程序中继续维护着这个IdleHandler,下次空闲时仍会再执会这个IdleHandler。但是如果消息队列里面有消息,但是他们的执行时间在当前时间之后,queueIdle也会被调用。
再往下看代码:
- /**
- * Add a new {@link IdleHandler} to this message queue. This may be
- * removed automatically for you by returning false from
- * {@link IdleHandler#queueIdle IdleHandler.queueIdle()} when it is
- * invoked, or explicitly removing it with {@link #removeIdleHandler}.
- *
- * <p>This method is safe to call from any thread.
- *
- * @param handler The IdleHandler to be added.
- */
- public final void addIdleHandler(IdleHandler handler) {
- if (handler == null) {
- throw new NullPointerException("Can't add a null IdleHandler");
- }
- synchronized (this) {
- mIdleHandlers.add(handler);
- }
- }
向消息队列中添加一个新的 MessageQueue.IdleHandler 。当调用 IdleHandler.queueIdle() 返回 false 时,此 MessageQueue.IdleHandler 会自动的从消息队列中移除。或者调用 removeIdleHandler(MessageQueue.IdleHandler) 也可以从消息队列中移除 MessageQueue.IdleHandler 。 这个方法是线程安全的。
有添加,就有删除:
- /**
- * Remove an {@link IdleHandler} from the queue that was previously added
- * with {@link #addIdleHandler}. If the given object is not currently
- * in the idle list, nothing is done.
- *
- * @param handler The IdleHandler to be removed.
- */
- public final void removeIdleHandler(IdleHandler handler) {
- synchronized (this) {
- mIdleHandlers.remove(handler);
- }
- }
从队列中移除之前调用 addIdlehandler(MessageQueue.IdleHandler) 添加的 MessageQueue.IdleHandler 。如果 handler 不在当前的空闲列表,不做任何事。
看一下它的构造方法:
- MessageQueue() {
- nativeInit();
- }
调用native代码,完成初始化。
重写了类的销毁:
- @Override
- protected void finalize() throws Throwable {
- try {
- nativeDestroy();
- } finally {
- super.finalize();
- }
- }
也是调用native代码,完成类的销毁。
下面就是获取下一个Message方法:
- final Message next() {
- int pendingIdleHandlerCount = -1; // -1 only during first iteration
- int nextPollTimeoutMillis = 0;
- for (;;) {
- if (nextPollTimeoutMillis != 0) {
- Binder.flushPendingCommands();
- }
- nativePollOnce(mPtr, nextPollTimeoutMillis);
- synchronized (this) {
- // Try to retrieve the next message. Return if found.
- final long now = SystemClock.uptimeMillis();
- final Message msg = mMessages;
- if (msg != null) {
- final long when = msg.when;
- if (now >= when) {
- mBlocked = false;
- mMessages = msg.next;
- msg.next = null;
- if (false) Log.v("MessageQueue", "Returning message: " + msg);
- msg.markInUse();
- return msg;
- } else {
- nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
- }
- } else {
- nextPollTimeoutMillis = -1;
- }
- // If first time, then get the number of idlers to run.
- if (pendingIdleHandlerCount < 0) {
- 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("MessageQueue", "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;
- }
- }
先看一下两个参数的意思:pendingIdleHandlerCount:空闲的handler个数。只有在第一次循环的时候值为-1。nextPollTimeoutMillis:字面理解下次轮询时间,如果当前消息队列中没有消息,它要等待的时候,for循环开始时,传入的值为0,表示不等待。
在for循环内部:
- if (nextPollTimeoutMillis != 0) {
- Binder.flushPendingCommands();
- }
如果nextPollTimeoutMillis值不为0,则等待消息。然后 执行下面语句是看看当前消息队列中有没有消息:
- nativePollOnce(mPtr, nextPollTimeoutMillis);
nativePollOnce返回后,next函数将从mMessages中提取一个消息。也就是说,要让nativePollOnce返回,至少要添加一个消息到消息队列,否则nativePollOnce不过是做了一次无用功罢了。
如果nativePollOnce在Native层等待,就表明Native层也可以投递Message(消息,为了适应业界的习惯本书沿用英文,必要时才用中文,其他词同此),但是从Message类的实现代码上看,该类和Native层没有建立任何关系(即Native层不太可能去构造Java层的Message对象并把它插入到Java层的Message队列中)。那么nativePollOnce在等待什么呢?
对于上面的问题,相信有些读者心中已有了答案:nativePollOnce除了等待Java层来的Message,还在Native层做了大量的工作。
然后再看synchronized内部代码:
- synchronized (this) {
- // Try to retrieve the next message. Return if found.
- final long now = SystemClock.uptimeMillis();
- final Message msg = mMessages;
- if (msg != null) {
- final long when = msg.when;
- if (now >= when) {
- mBlocked = false;
- mMessages = msg.next;
- msg.next = null;
- if (false) Log.v("MessageQueue", "Returning message: " + msg);
- msg.markInUse();
- return msg;
- } else {
- nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
- }
- } else {
- nextPollTimeoutMillis = -1;
- }
- // If first time, then get the number of idlers to run.
- if (pendingIdleHandlerCount < 0) {
- 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);
- }
先尝试检索出下一个message,如果存在就返回。如果message为空,nextPollTimeoutMillis就赋值为-1.就必须等待下一次消息。如果不为空,就判断时间是否可以处理这个消息,如果符合条件,把消息传给looper处理。否则,算出需要等待时间,等待到该时间,然后执行
- // If first time, then get the number of idlers to run.
- if (pendingIdleHandlerCount < 0) {
- pendingIdleHandlerCount = mIdleHandlers.size();
- }
- if (pendingIdleHandlerCount == 0) {
- // No idle handlers to run. Loop and wait some more.
- mBlocked = true;
- continue;
- }
如果是第一次,得到闲置的idler handler去运行。如果没有闲置的idlehandler,阻塞,然后继续循环等待更多消息。
- if (mPendingIdleHandlers == null) {
- mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
- }
- mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
接下来就是执行这些注册了的IdleHanlder了:
- // 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("MessageQueue", "IdleHandler threw exception", t);
- }
- if (!keep) {
- synchronized (this) {
- mIdleHandlers.remove(idler);
- }
- }
- }
运行空闲处理器。我们只能达到这个代码块在第一次迭代。执行完这些IdleHandler之后,线程下次调用nativePollOnce函数时,就不设置超时时间了,因为,很有可能在执行IdleHandler的时候,已经有新的消息加入到消息队列中去了,因此,要重置nextPollTimeoutMillis的值:
- // 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;
再接下来就是插入操作:
- final boolean enqueueMessage(Message msg, long when) {
- if (msg.isInUse()) {
- throw new AndroidRuntimeException(msg
- + " This message is already in use.");
- }
- if (msg.target == null && !mQuitAllowed) {
- throw new RuntimeException("Main thread not allowed to quit");
- }
- final boolean needWake;
- synchronized (this) {
- if (mQuiting) {
- RuntimeException e = new RuntimeException(
- msg.target + " sending message to a Handler on a dead thread");
- Log.w("MessageQueue", e.getMessage(), e);
- return false;
- } else if (msg.target == null) {
- mQuiting = true;
- }
- msg.when = when;
- //Log.d("MessageQueue", "Enqueing: " + msg);
- Message p = mMessages;
- if (p == null || when == 0 || when < p.when) {
- msg.next = p;
- mMessages = msg;
- needWake = mBlocked; // new head, might need to wake up
- } else {
- Message prev = null;
- while (p != null && p.when <= when) {
- prev = p;
- p = p.next;
- }
- msg.next = prev.next;
- prev.next = msg;
- needWake = false; // still waiting on head, no need to wake up
- }
- }
- if (needWake) {
- nativeWake(mPtr);
- }
- return true;
- }
- if (msg.isInUse()) {
- throw new AndroidRuntimeException(msg
- + " This message is already in use.");
- }
- if (msg.target == null && !mQuitAllowed) {
- throw new RuntimeException("Main thread not allowed to quit");
- }
- if (mQuiting) {
- RuntimeException e = new RuntimeException(
- msg.target + " sending message to a Handler on a dead thread");
- Log.w("MessageQueue", e.getMessage(), e);
- return false;
- } else if (msg.target == null) {
- mQuiting = true;
- }
是否正在退出,如果退出,返回false,如果msg对应的handler为空,把正在退出设为true。
- Message p = mMessages;
- if (p == null || when == 0 || when < p.when) {
- msg.next = p;
- mMessages = msg;
- needWake = mBlocked; // new head, might need to wake up
- } else {
- Message prev = null;
- while (p != null && p.when <= when) {
- prev = p;
- p = p.next;
- }
- msg.next = prev.next;
- prev.next = msg;
- needWake = false; // still waiting on head, no need to wake up
- }
如果p为空,或者when=0或者插入时间小于p.when时,就会把传入的消息插入到队列头(这也就解释了上篇文章中提到的问题,when=0时,插入队列头部),否则,插入队尾。
接下来是删除。
- final boolean removeMessages(Handler h, int what, Object object,
- boolean doRemove) {
- synchronized (this) {
- Message p = mMessages;
- boolean found = false;
- // Remove all messages at front.
- while (p != null && p.target == h && p.what == what
- && (object == null || p.obj == object)) {
- if (!doRemove) return true;
- found = true;
- Message n = p.next;
- mMessages = n;
- p.recycle();
- 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)) {
- if (!doRemove) return true;
- found = true;
- Message nn = n.next;
- n.recycle();
- p.next = nn;
- continue;
- }
- }
- p = n;
- }
- return found;
- }
- }
- final void removeMessages(Handler h, Runnable r, Object object) {
- if (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.recycle();
- 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.recycle();
- p.next = nn;
- continue;
- }
- }
- p = n;
- }
- }
- }
- final void removeCallbacksAndMessages(Handler h, Object object) {
- 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.recycle();
- 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.recycle();
- p.next = nn;
- continue;
- }
- }
- p = n;
- }
- }
- }