之前我们分析过Android的消息机制,但是有一个空闲消息处理器我们没有分析过,这篇博客我们来看下。


一、MessageQueue空闲处理器

之前在分析MessageQueue的next函数,这个函数就是获取队列的下个Message,我们再来看下。

    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);//native函数,底层就是epoll机制            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);//下个Message的时间                    } 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;//返回message                    }                } else {                    // No more messages.                    nextPollTimeoutMillis = -1;//message为空,底层永久阻塞                }                // Process the quit message now that all pending messages have been handled.                if (mQuitting) {                    dispose();                    return null;                }                //当消息为空,或者消息时间没到 (这个时候代表线程空闲)                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);//把mIdleHandler的数据放入mPendingIdelHandlers            }            // 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();//调用IdleHandler的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;        }    }

上面这个函数是一个无线循环直到找到一个Message,先调用nativePollOnce,这个函数之前分析过是在c层调用epoll机制。然后继续分析,当有消息时,消息的时间没有,我们就计算下个消息的时间,下次传入nativePollOnce。当有消息时间到了,我们就返回该消息。如果没有消息naxtPollTimeoutMillis就为-1(永久阻塞)。

下面我们再来看看关于空闲消息处理器,首先只有第一次才会赋值给pendingIdleHandlerCount。其次一定要Message为空,或者Message还没有到时间(这样代表线程空闲)。这样才会赋值给pendingIdleHandlerCount, 然后把mIdleHandlers 给mPendingIdleHandlers。

最后遍历mPendingIdleHandlers,调用每一个IdleHandler 的queueIdle方法,调用完之后就去除这个IdleHandler。


下面我们再来看下IdleHandler 这个接口。是MessageQueue的内部接口。

    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();    }


二、举例(ActivityThread的Idler内部类)

下面我们通过一个例子,我们先来看ActivityThread的Idler类,这个类就是在Activity的线程空闲时,调用AMS的activityIdle函数。

    private class Idler implements MessageQueue.IdleHandler {        @Override        public final boolean queueIdle() {            ActivityClientRecord a = mNewActivities;            boolean stopProfiling = false;            if (mBoundApplication != null && mProfiler.profileFd != null                    && mProfiler.autoStopProfiler) {                stopProfiling = true;            }            if (a != null) {                mNewActivities = null;                IActivityManager am = ActivityManagerNative.getDefault();                ActivityClientRecord prev;                do {                    if (localLOGV) Slog.v(                        TAG, "Reporting idle of " + a +                        " finished=" +                        (a.activity != null && a.activity.mFinished));                    if (a.activity != null && !a.activity.mFinished) {                        try {                            am.activityIdle(a.token, a.createdConfig, stopProfiling);                            a.createdConfig = null;                        } catch (RemoteException ex) {                            // Ignore                        }                    }                    prev = a;                    a = a.nextIdle;                    prev.nextIdle = null;                } while (a != null);            }            if (stopProfiling) {                mProfiler.stopProfiling();            }            ensureJitEnabled();            return false;        }    }
我们来看看其实现方法,是在ActivityThread的handleResumeActivity函数中有下面一段代码,调用了MessageQueue的addIdleHandler函数。

......            if (!r.onlyLocalRequest) {                r.nextIdle = mNewActivities;                mNewActivities = r;                if (localLOGV) Slog.v(                    TAG, "Scheduling idle handler for " + r);                Looper.myQueue().addIdleHandler(new Idler());            }......

addIdleHandler就是往mIdleHandlers成员变量加入给IdleHandler。

    public void addIdleHandler(@NonNull IdleHandler handler) {        if (handler == null) {            throw new NullPointerException("Can't add a null IdleHandler");        }        synchronized (this) {            mIdleHandlers.add(handler);        }    }
这样最后当这个Activity的线程空闲的时候,就会调用该IdleHandler的queueIdle。也就是最后调用AMS的activityIdle函数。




更多相关文章

  1. Android学习07-----事件处理(3)监听日期与时间的改变_焦点事件_
  2. Android 的消息机制(Handler消息传递机制)
  3. Android下使用dlopen函数动态调用.so链接库
  4. Android 异步消息处理机制的几种实现
  5. Android 异步消息处理机制(Handler 、 Looper 、MessageQueue)源码
  6. Android消息机制之ThreadLocal浅析
  7. Android消息循环机制源码深入理解

随机推荐

  1. Android(安卓)Notification(Android(安卓)
  2. 2018-08-17 Android(安卓)Gradle(1)
  3. 你需要知道的Android(安卓)View的测量
  4. Android(安卓)修改framework实现 全局唯
  5. Android(安卓)开发 Adb等常用指令集
  6. Android(安卓)进程状态的概念
  7. Android布局优化【面试篇】
  8. android背景与style的设置
  9. 【Android】Android 权限大全
  10. Android API 中文(14) —— ViewStub