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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值