得意犹堪夸世俗,诏黄新湿字如鸦。这篇文章主要讲述Android源码学习 Handler之MessageQueue相关的知识,希望能为你提供帮助。
消息出队
MessageQueue封装了以单向列表实现的Message队列。在Looper循环中,通过调用MessageQueue的next()方法将队首元素出队进行处理:
1 Message next() { 2// Return here if the message loop has already quit and been disposed. 3// This can happen if the application tries to restart a looper after quit 4// which is not supported. 5final long ptr = mPtr; 6if (ptr == 0) { 7return null; 8} 9 10int pendingIdleHandlerCount = -1; // -1 only during first iteration 11int nextPollTimeoutMillis = 0; 12for (; ; ) { 13if (nextPollTimeoutMillis != 0) { 14Binder.flushPendingCommands(); 15} 16 17nativePollOnce(ptr, nextPollTimeoutMillis); 18 19synchronized (this) { 20// Try to retrieve the next message.Return if found. 21final long now = SystemClock.uptimeMillis(); 22Message prevMsg = null; 23Message msg = mMessages; 24if (msg != null & & msg.target == null) { 25// Stalled by a barrier.Find the next asynchronous message in the queue. 26do { 27prevMsg = msg; 28msg = msg.next; 29} while (msg != null & & !msg.isAsynchronous()); 30} 31if (msg != null) { 32if (now < msg.when) { 33// Next message is not ready.Set a timeout to wake up when it is ready. 34nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); 35} else { 36// Got a message. 37mBlocked = false; 38if (prevMsg != null) { 39prevMsg.next = msg.next; 40} else { 41mMessages = msg.next; 42} 43msg.next = null; 44if (DEBUG) Log.v(TAG, "Returning message: " + msg); 45msg.markInUse(); 46return msg; 47} 48} else { 49// No more messages. 50nextPollTimeoutMillis = -1; 51} 52 53// Process the quit message now that all pending messages have been handled. 54if (mQuitting) { 55dispose(); 56return null; 57} 58 59// If first time idle, then get the number of idlers to run. 60// Idle handles only run if the queue is empty or if the first message 61// in the queue (possibly a barrier) is due to be handled in the future. 62if (pendingIdleHandlerCount < 0 63& & (mMessages == null || now < mMessages.when)) { 64pendingIdleHandlerCount = mIdleHandlers.size(); 65} 66if (pendingIdleHandlerCount < = 0) { 67// No idle handlers to run.Loop and wait some more. 68mBlocked = true; 69continue; 70} 71 72if (mPendingIdleHandlers == null) { 73mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)]; 74} 75mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers); 76} 77 78// Run the idle handlers. 79// We only ever reach this code block during the first iteration. 80for (int i = 0; i < pendingIdleHandlerCount; i++) { 81final IdleHandler idler = mPendingIdleHandlers[i]; 82mPendingIdleHandlers[i] = null; // release the reference to the handler 83 84boolean keep = false; 85try { 86keep = idler.queueIdle(); 87} catch (Throwable t) { 88Log.wtf(TAG, "IdleHandler threw exception", t); 89} 90 91if (!keep) { 92synchronized (this) { 93mIdleHandlers.remove(idler); 94} 95} 96} 97 98// Reset the idle handler count to 0 so we do not run them again. 99pendingIdleHandlerCount = 0; 100 101// While calling an idle handler, a new message could have been delivered 102// so go back and look again for a pending message without waiting. 103nextPollTimeoutMillis = 0; 104} 105 }
当队首元素执行时间未 或 队首元素为SyncBarrier且队列中没有asynchronous的Message 或 队列为空时,会执行IdleHandler(通过addIdleHandler和removeIdleHandler进行添加和移除)的queueIdle回调或者睡眠(nativePollOnce)。nativePollOnce与OnFileDescriptorEventListener相关,底层是基于Linux的epoll实现的,具体能用来干啥笔者也并不清楚,此处就把它当作定时睡眠操作吧。
第24行,对msg.target判空,通过postSyncBarrier发送的Message的target字段为空,即当队首Message是SyncBarrier时,会在队列中查找asynchronous的Message进行处理,而非asynchronous的Message将被阻塞。
第54行,若mQuitting为真,则返回null,从而导致Looper退出循环,结束Looper的执行。
消息入队
向Handler上发送消息,最终都通过enqueueMessage放入MessageQueue队列中:
1 boolean enqueueMessage(Message msg, long when) { 2if (msg.target == null) { 3throw new IllegalArgumentException("Message must have a target."); 4} 5if (msg.isInUse()) { 6throw new IllegalStateException(msg + " This message is already in use."); 7} 8 9synchronized (this) { 10if (mQuitting) { 11IllegalStateException e = new IllegalStateException( 12msg.target + " sending message to a Handler on a dead thread"); 13Log.w(TAG, e.getMessage(), e); 14msg.recycle(); 15return false; 16} 17 18msg.markInUse(); 19msg.when = when; 20Message p = mMessages; 21boolean needWake; 22if (p == null || when == 0 || when < p.when) { 23// New head, wake up the event queue if blocked. 24msg.next = p; 25mMessages = msg; 26needWake = mBlocked; 27} else { 28// Inserted within the middle of the queue.Usually we don‘t have to wake 29// up the event queue unless there is a barrier at the head of the queue 30// and the message is the earliest asynchronous message in the queue. 31needWake = mBlocked & & p.target == null & & msg.isAsynchronous(); 32Message prev; 33for (; ; ) { 34prev = p; 35p = p.next; 36if (p == null || when < p.when) { 37break; 38} 39if (needWake & & p.isAsynchronous()) { 40needWake = false; 41} 42} 43msg.next = p; // invariant: p == prev.next 44prev.next = msg; 45} 46 47// We can assume mPtr != 0 because mQuitting is false. 48if (needWake) { 49nativeWake(mPtr); 50} 51} 52return true; 53 }
enqueueMessage通过when字段维护队列中Message的先后循序。
第22行,当队列为空 或 when为0 或 when小于队首元素的when,则将Message放入队首。通过Handler的postAtFrontOfQueue和sendMessageAtFrontOfQueue提交的Runnable和Message满足when为0。
消息移除
removeMessages(Handler h, int what, Object object)、removeMessages(Handler h, Runnable r, Object object)、removeCallbacksAndMessages(Handler h, Object object)用于移除消息。这三个函数底层实现基本类似,分两步操作:1) 循环移除满足条件的Message,直到其不位于队首;2) 移除剩余的满足条件Message:
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; } } }
【Android源码学习 Handler之MessageQueue】
推荐阅读
- Android系统的启动时间
- Android中的Shape,RoundRectShape,ArcShape, OvalShape
- Android消息传递之EventBus 3.0
- Application 应用对象
- Android MD5加密RSA加密
- android studio 使用adb
- Android Studio中的Java控制台中出现乱码问题()
- 安卓笔记一
- 1.appium介绍