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

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

回头接着看View.post()

    /**
     * 

Causes the Runnable to be added to the message queue. * The runnable will be run on the user interface thread.

* * @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[] append(T[] array, int currentSize, T element) {
        assert currentSize <= array.length;

        if (currentSize + 1 > array.length) {
            @SuppressWarnings("unchecked")
            T[] newArray = ArrayUtils.newUnpaddedArray(
                    (Class) 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)

你可能感兴趣的:(View.postDelayed()/post() 原理(2))