View.postDelayed()/post() 原理(2)
2017-08-09 10:58
141 查看
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)
相关文章推荐
- View.postDelayed()/post() 原理(1)
- View 中post与postDelayed的区别
- Android控件postDelayed用法,View自带的定时器
- 从源码角度分析postDelayed原理
- Android控件postDelayed用法,View自带的定时器
- View.post获取控件宽高原理探索
- listView 添加addHeaderView和addFooterView以及handler.postDelayed的使用
- [android小知识]removeCallbacks与postDelayed的恩怨史(removeCallbacks所谓的无效, View和Handler 的postDelayed)
- listView 添加addHeaderView和addFooterView以及handler.postDelayed的使用
- HTTP中Get与Post、ViewState 原理
- UIScrollView 原理详解
- Android中View(视图)绘制不同状态背景图片原理深入分析以及StateListDrawable使用详解
- 滑动效果ViewFlipper使用原理
- nodejs-post文件上传原理详解
- nodejs-post文件上传原理详解
- iOS关于webview使用POST带参数的请求
- Android View的点击事件导致文字颜色变化的实现原理
- Android - View绘图原理总结
- ViewDragHelper 部分原理分析
- UIScrollView 原理(转载)