簡單講下postInvalidate和Invalidate的區別
阿新 • • 發佈:2018-11-27
invalidate
這裡我們從原始碼中去簡單扒一下View的invalidate()的方法:
1 /** 2 * Invalidate the whole view. If the view is visible, 3 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in 4 * the future. 5 * <p> 6 * This must be called from a UI thread. To call from a non-UI thread, call 7 * {@link #postInvalidate()}. 8 */ 9 public void invalidate() { 10 invalidate(true); 11 }
從方法中的註釋中看,我們知道invalidate方法會重新整理整個View,並且當這個View的可見性為VISIBLE的時候,View的onDraw()方法將會被呼叫。另外注意的是這個方法只能在UI執行緒中去呼叫。
上面就能夠基本知道invalidate方法是幹什麼的了。我們往下接著看原始碼:
1 /** 2 * This is where the invalidate() work actually happens. A full invalidate() 3 * causes the drawing cache to be invalidated, but this function can be 4 * called with invalidateCache set to false to skip that invalidation step 5 * for cases that do not need it (for example, a component that remains at 6 * the same dimensions with the same content). 7 * 8 * @param invalidateCache Whether the drawing cache for this view should be 9 * invalidated as well. This is usually true for a full 10 * invalidate, but may be set to false if the View's contents or 11 * dimensions have not changed. 12 * @hide 13 */ 14 public void invalidate(boolean invalidateCache) { 15 invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true); 16 }
我們看到,invalidate()方法中是呼叫invalidate(true),引數true的意思是需要整體重新整理,當View的內容和大小沒有任何變化時我們可以傳入false。重新整理的細節這裡不做詳細介紹。
postInvalidate
接下來看下postInvalidate()的實現:
1 /** 2 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop. 3 * Use this to invalidate the View from a non-UI thread.</p> 4 * 5 * <p>This method can be invoked from outside of the UI thread 6 * only when this View is attached to a window.</p> 7 * 8 * @see #invalidate() 9 * @see #postInvalidateDelayed(long) 10 */ 11 public void postInvalidate() { 12 postInvalidateDelayed(0); 13 } 14 15 public void postInvalidateDelayed(long delayMilliseconds) { 16 // We try only with the AttachInfo because there's no point in invalidating 17 // if we are not attached to our window 18 final AttachInfo attachInfo = mAttachInfo; 19 if (attachInfo != null) { 20 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds); 21 } 22 } 23 24 public void dispatchInvalidateDelayed(View view, long delayMilliseconds) { 25 Message msg = mHandler.obtainMessage(MSG_INVALIDATE, view); 26 mHandler.sendMessageDelayed(msg, delayMilliseconds); 27 }
從上面的方法註釋中可以知道,postInvalidate是可以在非UI執行緒中去呼叫重新整理UI的,那是如何做到的呢?從上面的方法呼叫棧中可以看出來,呼叫postInvalidate方法最後會呼叫View中的mHander傳送一個MSG_INVALIDATE的訊息。mHandler是ViewRootHandler的一個例項,從ViewRootHandler的handleMessage()方法中一探究竟(方法較長,只擷取部分):
1 @Override
2 public void handleMessage(Message msg) {
3 switch (msg.what) {
4 case MSG_INVALIDATE:
5 ((View) msg.obj).invalidate();
6 break;
7 case MSG_INVALIDATE_RECT:
8 final View.AttachInfo.InvalidateInfo info = (View.AttachInfo.InvalidateInfo) msg.obj;
9 info.target.invalidate(info.left, info.top, info.right, info.bottom);
10 info.recycle();
11 break;
12 case MSG_PROCESS_INPUT_EVENTS:
13 mProcessInputEventsScheduled = false;
14 doProcessInputEvents();
15 break;
在Handler中最後還是會呼叫View的invalidate()方法去重新整理,只不過postInvalidate()方法是通過Handler將重新整理事件通知發到Handler的handlerMessage中去執行invalidate的。
更多資訊可微信關注:南京Android部落