android源码解析--MessageQueue
2012-11-03 22:35
417 查看
上午,刚刚粗略的看完了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:
一个用于在一个线程为了等待更多消息阻塞时的接口。当消息队列为空,等待更多消息时,执行这个queueIdle函数,如果返回真,继续保持你的idlehandler的活跃状态,如果返回值为false,那么就会从应用程序中移除这个IdleHandler,否则的话就会在应用程序中继续维护着这个IdleHandler,下次空闲时仍会再执会这个IdleHandler。但是如果消息队列里面有消息,但是他们的执行时间在当前时间之后,queueIdle也会被调用。 再往下看代码:
向消息队列中添加一个新的MessageQueue.IdleHandler。当调用IdleHandler.queueIdle()返回false时,此MessageQueue.IdleHandler会自动的从消息队列中移除。或者调用removeIdleHandler(MessageQueue.IdleHandler)也可以从消息队列中移除MessageQueue.IdleHandler。这个方法是线程安全的。
有添加,就有删除:
从队列中移除之前调用addIdlehandler(MessageQueue.IdleHandler)添加的MessageQueue.IdleHandler。如果handler不在当前的空闲列表,不做任何事。
看一下它的构造方法:
调用native代码,完成初始化。重写了类的销毁:
也是调用native代码,完成类的销毁。下面就是获取下一个Message方法:
如果nextPollTimeoutMillis值不为0,则等待消息。然后执行下面语句是看看当前消息队列中有没有消息:
nativePollOnce返回后,next函数将从mMessages中提取一个消息。也就是说,要让nativePollOnce返回,至少要添加一个消息到消息队列,否则nativePollOnce不过是做了一次无用功罢了。
如果nativePollOnce在Native层等待,就表明Native层也可以投递Message(消息,为了适应业界的习惯本书沿用英文,必要时才用中文,其他词同此),但是从Message类的实现代码上看,该类和Native层没有建立任何关系(即Native层不太可能去构造Java层的Message对象并把它插入到Java层的Message队列中)。那么nativePollOnce在等待什么呢?
对于上面的问题,相信有些读者心中已有了答案:nativePollOnce除了等待Java层来的Message,还在Native层做了大量的工作。然后再看synchronized内部代码:
先尝试检索出下一个message,如果存在就返回。如果message为空,nextPollTimeoutMillis就赋值为-1.就必须等待下一次消息。如果不为空,就判断时间是否可以处理这个消息,如果符合条件,把消息传给looper处理。否则,算出需要等待时间,等待到该时间,然后执行
如果是第一次,得到闲置的idler handler去运行。如果没有闲置的idlehandler,阻塞,然后继续循环等待更多消息。
接下来就是执行这些注册了的IdleHanlder了:
运行空闲处理器。我们只能达到这个代码块在第一次迭代。执行完这些IdleHandler之后,线程下次调用nativePollOnce函数时,就不设置超时时间了,因为,很有可能在执行IdleHandler的时候,已经有新的消息加入到消息队列中去了,因此,要重置nextPollTimeoutMillis的值:
再接下来就是插入操作:
是否正在退出,如果退出,返回false,如果msg对应的handler为空,把正在退出设为true。
如果p为空,或者when=0或者插入时间小于p.when时,就会把传入的消息插入到队列头(这也就解释了上篇文章中提到的问题,when=0时,插入队列头部),否则,插入队尾。接下来是删除。
查看更多源码内容:Android源码解析!
先来看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; } }它在取Message来进行处理时通过判断MessageQueue里面的Message是否符合时间要求来决定是否需要把Message取出来做处理,通过这种方式做到消息的定时处理。所以调用这个函数的时候,有可能会让线程进入等待状态。什么情况下,线程会进入等待状态呢?两种情况,一是当消息队列中没有消息时,它会使线程进入等待状态;二是消息队列中有消息,但是消息指定了执行的时间,而现在还没有到这个时间,线程也会进入等待状态。消息队列中的消息是按时间先后来排序的。先看一下两个参数的意思: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);把注册在mIdleHandlers中的IdleHandler取出来,放在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"); }如果msg正在被使用,或者msg对应的handler为空或者不允许退出,均报异常。
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; } } }
查看更多源码内容:Android源码解析!
相关文章推荐
- 深入源码解析Android中的Handler,Message,MessageQueue,Looper
- Android Handler机制(二)---MessageQueue源码解析
- 深入源码解析Android中的Handler,Message,MessageQueue,Looper
- [Android] 异步消息处理机制(Handler 、 Looper 、MessageQueue)源码解析
- 深入源码解析Android中的Handler,Message,MessageQueue,Looper
- Android消息机制源码解析(四)——消息队列MessageQueue
- android MessageQueue 源码解析
- Android消息通信机制Handler详解,Handler,Looper,MessageQueue,源码解析,讲解这几个类怎么配合工作的
- Android消息机制Handler,MessageQueue,Looper源码解析
- Android中Looper,MessageQueue,ThreadLocal源码解析
- Android源码:Handler, Looper和MessageQueue实现解析
- 深入理解Android消息机制,从源码解析Handler,Looper,MessageQueue
- Android 异步消息处理机制(Handler 、 Looper 、MessageQueue)源码解析
- Android 异步消息处理机制(Handler 、 Looper 、MessageQueue)源码解析
- 深入源码解析Android中的Handler,Message,MessageQueue,Looper
- Android 异步消息处理机制(Handler 、 Looper 、MessageQueue)源码解析
- [Android] 异步消息处理机制(Handler 、 Looper 、MessageQueue)源码解析
- 深入源码解析Android中的Handler,Message,MessageQueue,Looper
- Android Looper、Message、Handler、MessageQueue源码解析
- Android发送消息相关类的源码解析,Handle,MessageQueue,Looper