Android MessageQueen详解
来源:互联网 发布:阿里云免费套餐9.9 编辑:程序博客网 时间:2024/06/05 02:57
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{@Overridepublic 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); } }
- Android MessageQueen详解
- Android handler Looper MessageQueen Message 关系
- Android消息机制之Looper、Handler、MessageQueen
- Android进阶——Android消息机制之Looper、Handler、MessageQueen
- 关于Handler以及Looper,MessageQueen等
- Handler、Looper、MessageQueen、Message的关系及个人理解
- 深入浅出,Handler机制外科手术式的剖析(ThreadLocal,Looper,MessageQueen,Message)(上)
- 深入浅出,Handler机制外科手术式的剖析(ThreadLocal,Looper,MessageQueen,Message)(下)
- android android:taskAffinity 详解
- [Android]Android.mk 详解
- 【Android】Android LogCat使用详解
- android中android:wight详解
- Android之android:layout_weight详解
- 【android】android Handler应用详解
- android android:layout_weight 属性详解
- Android之android:layout_weight详解
- 【Android】Android LogCat使用详解
- 【Android】Android开发规范详解
- Java String类
- MOOC 数据结构 Pop Sequence
- 2016-10-29 程序举例
- Java StringBuffer和StringBuilder类
- UVA 11922 Permutation Transformer(splay树)
- Android MessageQueen详解
- 7. GStreamer建议的学习步骤和网页链接汇总
- Java 数组
- this is the first time to use this.
- 环信即时通讯sdk使用时遇到的问题及解决
- 413. Arithmetic Slices
- Codves 1044 拦截导弹 ---1999年NOIP全国联赛提高组 dp(n2 || nlogn)
- C# WinForm窗体及其控件的自适应
- CSS 2 颜色