Android 启动优化-IdleHandler

  • 1、IdleHandler 的简单使用
  • 2、系统使用的案例
  • 3、IdleHandler的源码实现

1、IdleHandler 的简单使用

在Android中,当消息队列没有可处理的消息的时候,就是消息队列时空的,或者消息队列里的消息还没到可触发的时间,就会执行IdleHandler。

 Looper.myQueue().addIdleHandler(new IdleHandler()       {              @Override             public boolean queueIdle()               { //在这里可以加载一些业务没有这么快涉及三方的sdk                                   return false;  //false 只会触发一次 ,true空闲是都会返回              }               });

2、系统使用的案例

我们都知道,Android系统开启应用进程的时候,会调到ActivityThread类中的main()方法,在ActivityThread类中会用到,第一次idler的时候,调了一次GC。

 void scheduleGcIdler() {        if (!mGcIdlerScheduled) {            mGcIdlerScheduled = true;            Looper.myQueue().addIdleHandler(mGcIdler);        }        mH.removeMessages(H.GC_WHEN_IDLE);    }     final class GcIdler implements MessageQueue.IdleHandler {        @Override        public final boolean queueIdle() {            doGcIfNeeded();            return false;        }    }

在Instrumentation 类里边。

    public void waitForIdle(Runnable recipient) {        mMessageQueue.addIdleHandler(new Idler(recipient));        mThread.getHandler().post(new EmptyRunnable());    }   private static final class Idler implements MessageQueue.IdleHandler {        private final Runnable mCallback;        private boolean mIdle;        public Idler(Runnable callback) {            mCallback = callback;            mIdle = false;        }        public final boolean queueIdle() {            if (mCallback != null) {                mCallback.run();            }            synchronized (this) {                mIdle = true;                notifyAll();            }            return false;        }        public void waitForIdle() {            synchronized (this) {                while (!mIdle) {                    try {                        wait();                    } catch (InterruptedException e) {                    }                }            }        }    }

3、IdleHandler的源码实现

当我们调用 Looper.myQueue().addIdleHandler(new IdleHandler())的时候,会将当前的idle加入IdleHandler[] mPendingIdleHandlers,当消息队列没有可执行消息时,进入阻塞,就有回调 idler.queueIdle()

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

.

更多相关文章

  1. 浅析Android中的消息机制-解决:Only the original thread that cr
  2. Android异步消息机制之Handler
  3. Android调用.NET Webservice报org.ksoap2.serialization.SoapPri
  4. Android开发之消息处理机制(一)——Handler
  5. Titanium 使用刘明星的Jpush module做android端的消息推送
  6. Android(安卓)后台任务(五)Service
  7. android 电容屏(二):驱动调试之基本概念篇
  8. 我是新手,我在学Android
  9. Android(安卓)让按钮闪烁(点击的时候停止闪烁)

随机推荐

  1. android布局 LinearLayout和RelativeLayo
  2. Android学习—— Android资料之-系统自带
  3. android 参数含义
  4. CSDN 很经典的博客 您值得一览
  5. 那些年收藏的技术文章(一)-CSDN篇
  6. 为android 工程添加单元测试
  7. Android预定义样式
  8. Mono for Android试用体验
  9. Android短信----发送流程---框架层(Framew
  10. ANDROID url资源站