MessageQueue.next()方法都涉及哪些知识点

421 阅读2分钟

MessageQueue.next()

Message next() {  
    final long ptr = mPtr; //mPtr是通过native方法生成的code,作用是将其与Native层的消息队列绑定
    if (ptr == 0) {
       //如果没有与Native层的队列绑定则直接返回
        return null;
    }

    int pendingIdleHandlerCount = -1; //保存IdleHandler的个数
    int nextPollTimeoutMillis = 0; //下一次消息到来需要等待的时间
    for (;;) {
        if (nextPollTimeoutMillis != 0) {
            //没有需要等待的消息,释放资源。
            Binder.flushPendingCommands();
        }
        //1)nextPollTimeoutMillis > 0 进入阻塞,nextPollTimeoutMillis时间后再次获取消息   //2) nextPollTimeoutMillis < 0 进入阻塞等待唤醒
        nativePollOnce(ptr, nextPollTimeoutMillis);

        synchronized (this) {
            final long now = SystemClock.uptimeMillis(); //记录当前的时间
            Message prevMsg = null;
            Message msg = mMessages; //队列中的第一个消息
            if (msg != null && msg.target == null) {
                //发现有消息屏障(msg.target == null表示此消息为消息屏障)
                do {
                    prevMsg = msg;
                    msg = msg.next;
                } while (msg != null && !msg.isAsynchronous());//找到第一个异步消息
            }
            if (msg != null) {
                //找到了可执行消息
                if (now < msg.when) {
                    // 消息的执行时间还没有到,更新nextPollTimeoutMillis等待时间
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                    //到了执行的时间,控制队列不再阻塞,并操作当前队列移除这个消息。
                    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正在使用
                    msg.markInUse();
                    return msg; //返回这个消息
                }
            } else {
                //没有获取到可执行的消息 nextPollTimeoutMillis设置为-1,下一次循环会进入休眠状态
                nextPollTimeoutMillis = -1;
            }

            // Process the quit message now that all pending messages have been handled.
            if (mQuitting) {
                //如果队列需要退出,则退出循环返回null,同时销毁队列
                dispose();
                return null;
            }
            
            //接下来进行IdleHandler的处理
            if (pendingIdleHandlerCount < 0
                    && (mMessages == null || now < mMessages.when)) {
                // 初始化IdleHandler的个数    
                pendingIdleHandlerCount = mIdleHandlers.size();
            }
            if (pendingIdleHandlerCount <= 0) {
                //没有需要执行的IdelHandler则继续下一次循环
                mBlocked = true;
                continue;
            }
            //存储IdleHandler的数组最小长度是4
            if (mPendingIdleHandlers == null) {
                mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
            }
            mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);//从mIdleHandlers里面进行拷贝
        }

        //依次执行IdleHandler
        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) {
                //keep为true则执行完毕不移除,下次可继续执行,否则移除。
                synchronized (this) {
                    mIdleHandlers.remove(idler);
                }
            }
        }

        //重置等待时间和idleHandler个数
        pendingIdleHandlerCount = 0;
        nextPollTimeoutMillis = 0;
    }
}

执行步骤

1)通过native方法生成的code,将其与Native层的消息队列绑定。

2)判断是否需要阻塞等待(等待多长时间)。

3)判断是否有消息屏障,有屏障则取出第一个异步消息。

4)消息到达了执行时间就立即执行,否则在下一次循环阻塞等待。

5)当前没有可执行的消息则进行处理IdleHandler

总结

1)通过与Native队列建立关联实现阻塞和唤醒。

2)优先处理异步消息,如果消息没有到达执行时间则阻塞等待。

3)没有可执行消息则执行IdleHandler