View.postDelayed()/post() 原理(2)

来源:互联网 发布:世界地图历史演变软件 编辑:程序博客网 时间:2024/06/03 20:34

1.2 post到自身的一个runnable队列中

回头接着看View.post()

    /**     * <p>Causes the Runnable to be added to the message queue.     * The runnable will be run on the user interface thread.</p>     *     * @param action The Runnable that will be executed.     *     * @return Returns true if the Runnable was successfully placed in to the     *         message queue.  Returns false on failure, usually because the     *         looper processing the message queue is exiting.     *     * @see #postDelayed     * @see #removeCallbacks     */    public boolean post(Runnable action) {        final AttachInfo attachInfo = mAttachInfo;        if (attachInfo != null) {            return attachInfo.mHandler.post(action);        }        // Postpone the runnable until we know on which thread it needs to run.        // Assume that the runnable will be successfully placed after attach.        getRunQueue().post(action);        return true;    }

当mAttachInfo为null,即View没有attach到Window时,会把Runnable缓存到Run Queue,并且直接返回true。来看看getRunQueue():

    /**     * Returns the queue of runnable for this view.     *     * @return the queue of runnables for this view     */    private HandlerActionQueue getRunQueue() {        if (mRunQueue == null) {            mRunQueue = new HandlerActionQueue();        }        return mRunQueue;    }

这也是一个懒加载,并且可以看到没有做线程安全,显然是内部保证只在UI线程调用。从HanderActionQueue的类定义可以看到其功用:

/** * Class used to enqueue pending work from Views when no Handler is attached. * * @hide Exposed for test framework only. */public class HandlerActionQueue

在View.dispatchAttachedToWindow()中,有消费缓存到Run Queue的Runnable的逻辑:

        mAttachInfo = info;        ......        // Transfer all pending runnables.        if (mRunQueue != null) {            mRunQueue.executeActions(info.mHandler);            mRunQueue = null;        }

并且可以看到一旦dispatch并在mAttachInfo.mHandler中执行了缓存的Runnable,立刻解除mRunQueue的强引用,废弃掉HanderActionQueue对象。
在mAttachInfo.mHandler中执行,也意味着和1.1那一路逻辑是等效的。
多说一些,在HanderActionQueue(源代码与View同包)内部,使用了一个可增长数组来做缓存队列。HanderActionQueue.post():

    public void post(Runnable action) {        postDelayed(action, 0);    }    public void postDelayed(Runnable action, long delayMillis) {        final HandlerAction handlerAction = new HandlerAction(action, delayMillis);        synchronized (this) {            if (mActions == null) {                mActions = new HandlerAction[4];            }            mActions = GrowingArrayUtils.append(mActions, mCount, handlerAction);            mCount++;        }    }

先创建(线程安全)一个size为4的数组,然后使用GrowingArrayUtils.append()做可增长数组放入item。
GrowingArrayUtils这个类位于frameworks/base/core/java/com/android/internal/util/GrowingArrayUtils.java,是Android框架层的一个内部工具类。看看它相关的代码:

    /**     * Appends an element to the end of the array, growing the array if there is no more room.     * @param array The array to which to append the element. This must NOT be null.     * @param currentSize The number of elements in the array. Must be less than or equal to     *                    array.length.     * @param element The element to append.     * @return the array to which the element was appended. This may be different than the given     *         array.     */    public static <T> T[] append(T[] array, int currentSize, T element) {        assert currentSize <= array.length;        if (currentSize + 1 > array.length) {            @SuppressWarnings("unchecked")            T[] newArray = ArrayUtils.newUnpaddedArray(                    (Class<T>) array.getClass().getComponentType(), growSize(currentSize));            System.arraycopy(array, 0, newArray, 0, currentSize);            array = newArray;        }        array[currentSize] = element;        return array;    }
    /**     * Given the current size of an array, returns an ideal size to which the array should grow.     * This is typically double the given size, but should not be relied upon to do so in the     * future.     */    public static int growSize(int currentSize) {        return currentSize <= 4 ? 8 : currentSize * 2;    }

可以看到是做过一些优化。可以作为类似需求的List之外的一种选择。如有时间,后续研究对比一下。(完)
View.postDelayed()/post() 原理(1)
View.postDelayed()/post() 原理(2)

阅读全文
0 0
原创粉丝点击