Android View之View.post()分析

你們都知道每一個View都有一個post()和postDelayed()方法,那麼這兩個方法是作什麼用呢?何時須要用呢?android

咱們帶着這兩個問題來分析一下:緩存

首先咱們看下這兩個方法的源碼,首先看post():app

/**

*
<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;

}oop

從源碼中咱們很清楚的看到,兩種狀況:post

1.當mAttachInfo != null 時,post方法最終是由attachInfo中的mHandler調用post來處理,從而保證在ui線程中執行,因此從根本上來以後的整個流程仍是Handler 的整個處理機制流程(Handler的處理機制流程,這裏不作分析),那麼mAttachInfo又是何時賦值的呢?搜索一下源碼看到:ui

/**

*
@param
info
the {
@link
android.view.View.AttachInfo} to associated with

* this view

*/

void dispatchAttachedToWindow(AttachInfo info, int visibility) {
mAttachInfo = info;
if (mOverlay != null) {
mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);

}this


能夠看到mAttachInfo是在,dispatchAttachedToWindow中調用的,而dispatchAttachedToWindow 是在 ViewRootImpl 類的performTraversals 調用的,而這個方法在view初始化的時候會被調用。spa

2.mAttachInfo==null時,調用getRunQueue().post(action),咱們來看下這個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;

}orm


這裏看到最終調用的是HandlerActionQueue的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++;
}

}

這裏咱們看到基本上就是經過HandlerActionQueue緩存起來,緩存起來何時執行呢?咱們找下HandlerActionQueue的源碼裏:

public void executeActions(Handler handler) {
synchronized (this) {
final HandlerAction[] actions = mActions;
for (int i = 0, count = mCount; i < count; i++) {
final HandlerAction handlerAction = actions[i];
handler.postDelayed(handlerAction.action, handlerAction.delay);
}

mActions = null;
mCount = 0;
}

}

緩存起來的runnable最終仍是經過handler來執行,直接找到執行的代碼:


仍是經過dispatchAttachedToWindow來執行。

這兩個方法:

當打開一個activity時若是調用post方法時尚未開始執行dispatchAttachedToWindow就先調用getRunQueue().post(action)緩存起來,當執行到dispatchAttachedToWindow時再執行handler的post,若是到達就直接執行handler.post。

總結:post()和postDelayed()用來更新ui,postDelayed能夠設置延時。

相關文章
相關標籤/搜索