转载:android addIdleHandler 空闲线程 源码分析

描述
在项目中偶然看到其他人有在用

Looper.myQueue().addIdleHandler(new IdleHandler() {    @Override    public boolean queueIdle() {        ...        return false;    }}

之前一直不知道这么写是怎么回事, 今天特意研究了一下源码, 搞清楚了IdleHandler的机制.


源码分析
我们先来看下IdleHandler的add跟remove方法

/** * Callback interface for discovering when a thread is going to block * waiting for more messages. */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 {@link IdleHandler} to this message queue.  This may be * removed automatically for you by returning false from * {@link IdleHandler#queueIdle IdleHandler.queueIdle()} when it is * invoked, or explicitly removing it with {@link #removeIdleHandler}. * * 

This method is safe to call from any thread. * * @param handler The IdleHandler to be added. */public void addIdleHandler(@NonNull IdleHandler handler) { if (handler == null) { throw new NullPointerException("Can't add a null IdleHandler"); } synchronized (this) { mIdleHandlers.add(handler); }}/** * Remove an {@link IdleHandler} from the queue that was previously added * with {@link #addIdleHandler}. If the given object is not currently * in the idle list, nothing is done. * *

This method is safe to call from any thread. * * @param handler The IdleHandler to be removed. */public void removeIdleHandler(@NonNull IdleHandler handler) { synchronized (this) { mIdleHandlers.remove(handler); }}

IdleHandler接口表示当MessageQueue发现当前没有更多消息可以处理的时候, 则顺便干点别的事情的callback函数(即如果发现idle了,
那就找点别的事干). callback函数有个boolean的返回值, 表示是否keep. 如果返回false, 则它会在调用完毕之后从mIdleHandlers中移除.

接下来看MessageQueue的核心方法—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 iterationint 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.            // 这里执行的操作是忽略所有的同步消息, 知道找出queue中的异步消息            // 我理解是这个的同步消息会造成线程的阻塞, 所以忽略同步的消息            do {                prevMsg = msg;                msg = msg.next;            } while (msg != null && !msg.isAsynchronous());        }        // 走到这一步, 有两种可能,        // 一种是遍历到队尾没有发现异步消息,        // 另一种是找到queue中的第一个异步消息        if (msg != null) {            // 找到queue中的第一个异步消息            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.                // 当前消息到达可以执行的时间, 直接返回这个msg                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.        // 如果queue中没有msg, 或者msg没到可执行的时间,        // 那么现在线程就处于空闲时间了, 可以执行IdleHandler了        if (pendingIdleHandlerCount < 0                && (mMessages == null || now < mMessages.when)) {            // pendingIdleHandlerCount在进入for循环之前是被初始化为-1的            // 并且没有更多地消息要进行处理            pendingIdleHandlerCount = mIdleHandlers.size();        }        if (pendingIdleHandlerCount <= 0) {            // No idle handlers to run. Loop and wait some more.            // 如果没有IdleHandler要进行处理, 则直接进入下次循环            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.    // 退出同步块, 接下来就可以执行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) {            // 如果之前addIdleHandler中返回为false,            // 就在执行完这个IdleHandler的callback之后, 将这个idler移除掉            synchronized (this) {                mIdleHandlers.remove(idler);            }        }    }    // Reset the idle handler count to 0 so we do not run them again.    // 全部执行完, 重新设置这个值为0, 以便下次可以再次执行    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;}}

引用自:android中IdleHandler的使用
IdleHandler 在API上面的解释如下:

public final void addIdleHandler (MessageQueue.IdleHandler handler)

向消息队列中添加一个新的MessageQueue.IdleHandler。当调用IdleHandler.queueIdle()返回false时,此MessageQueue.IdleHandler会自动的从消息队列中移除。或者调用removeIdleHandler(MessageQueue.IdleHandler)也可以从消息队列中移除MessageQueue.IdleHandler。

此方法是线程安全的。

  参数        handler              要添加的IdleHandler。

具体用法我是用在 android初始化activty界面时使用的。如果想用android做一个播放器,如果下面包括播放进度条,暂停、停止等按钮的控件用popWindow实现的话。就是在程序一起来然后下面的popWindow就要显示在activty上。用这个是比较好的,当然你可以用myHandler.sendEmptyMessage() 去你想要的操作。

把IdleHandler用在onCreate ( )里面,用法很简单如下:

Looper.myQueue().addIdleHandler(new IdleHandler()     {            @Override            public boolean queueIdle()             {                // TODO Auto-generated method stub                //你想做的任何事情                //........                //........                return false;              }     });

更多相关文章

  1. Android(安卓)4编程入门经典—开发智能手机与平板电脑应用
  2. android anr traces日志分析方法
  3. Android(安卓)当前线程是否为主线程(UI线程)
  4. Android(安卓)App 内存泄露之Handler
  5. java虚拟机理解
  6. runOnUiThread
  7. Android(安卓)使用 kotlin 协程
  8. Android(安卓)API之Telephony.Sms
  9. 不能创建处理器 Can't create handler inside thread that has n

随机推荐

  1. Google Android(安卓)应用程序结构
  2. OpenGL ES for Android(安卓)环境搭建
  3. Android自动化测试工具——Monkey
  4. Android中外部程序调用方法总结
  5. Android之Bluetooth
  6. 远程调测:Chrome on Android之三 调测WebV
  7. Android应用程序启动过程源代码分析
  8. 【笔记】android sdk集成的eclipse中导入
  9. 系出名门 Android(安卓)系列文章索引
  10. 系出名门Android(9) - 数据库支持(SQLite