IdleHandler 分析

前言

作为系统最重要的部分之一。Handler可以说是面试必问。本文只要还是介绍 Handler 中的一点IdleHandler。关于Handler其他细节可以参考之前笔者记录分析的从源码分析Handler面试问题

IdleHandler 是什么

Handler源码中能够找到 如下接口。其注释部分就很好的解释了其作用。简单概述

当消息队列中没有立刻执行的消息时候执行idleHandler的任务

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();
}
复制代码

如何使用

Handler提供了两个方法

public void addIdleHandler(@NonNull IdleHandler handler) {
    if (handler == null) {
        throw new NullPointerException("Can't add a null IdleHandler");
    }
    synchronized (this) {
        mIdleHandlers.add(handler);
    }
}
复制代码
public void removeIdleHandler(@NonNull IdleHandler handler) {
    synchronized (this) {
        mIdleHandlers.remove(handler);
    }
}
复制代码

使用起来也非常简单了

Looper.myQueue().addIdleHandler{
    Log.i(TAG, "this is meeage")
    false
}
复制代码

源码分析

首先从addIdleHandler开始分析。将IdleHandler添加到了mIdleHandlers

这个mIdleHandlers就是一个数组。用来存放idle任务的

private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
复制代码

我们都知道 Handler是在MessageQueue中将消息取出。这里我们具体分析一下IdleHandler是如何在没有立刻执行的消息时候去执行此任务。

  Message next() {
 
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }
        // ?  下面 默认的 idle 任务数量是 -1 
        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());
                }
                // ? 看到这里 此时如果msg 为空 说明。此时队列中是没有消息的。也就是所谓的空闲状态
                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();
                        // ? 当有任务的时候 直接返回 不会执行到 idle 的任务
                        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;
                }

                // ?  pendingIdleHandlerCount默认是 -1
                if (pendingIdleHandlerCount < 0
                        // 并且满足了 当前没有消息的时候
                        && (mMessages == null || now < mMessages.when)) {
                    // 记录我们保存的 idle 任务数量
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                if (pendingIdleHandlerCount <= 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }
                // ? 默认是null 会创建一个数组 用于存放 idle任务
                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }

            
            // ? 将 idle 的任务 执行
            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 {
                    // ? idle 的接口是有一个返回值的。
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }
                
                // ? 当 返回值是 false只执行一次。当返回true 则 循环执行
                if (!keep) {
                    synchronized (this) {
                        // ? 当返回false 则会删除 这个 idle 任务
                        mIdleHandlers.remove(idler);
                    }
                }
            }

            // ? 重置 idle 任务的数量
            // 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;
        }
    }
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享