一般情況
invalidate()調用 只會導致draw()方法的調用,而measure()、layout() 則不會。
requestLayout()則相反,只會 調用measure()、layout(),而不會調用draw()。
總的來說,在這兩個函數上的區(qū)別很重要的一點就是:layoutRequested 是否為true.
原因:invalidate() 的時候, mLayoutRequested 變量不會被 設置為true。
requestLayout() , requestLayout如果沒有改變視圖大小,那就不會觸發(fā)onDraw,其根據layoutRequested為真,measureHierarchy會調用,即measure()調用,之后也就調用了layout()。
與invalidate()相關的兩個標志位
PFLAG_INVALIDATED、PFLAG_DRAWING_CACHE_VALID
invalidate()會不斷向上查找 ViewParent,直到ViewRootImpl,在這個向上的過程中,只有調用invalidate()方法的View才會將PFLAG_INVALIDATED標志置1,其他的View不會。而所有的View都是將PFLAG_DRAWING_CACHE_VALID置0。
在向下分發(fā)draw()的時候,又根據PFLAG_INVALIDATED 位是否為1 且PFLAG_DRAWING_CACHE_VALID位為0 的條件來確定View重繪。
想一想:既然這個過程是先向上查詢,再向下分發(fā)的過程,那為什么不直接對view繪制,而是這樣轉一圈?
我的理解是復用的scheduleTraversals()原因。而這個函數同樣是requestLayout()該當的核心方法。而requestLayout()則相對于調用的view來說,自己的視圖大小改變,必須會涉及到父控件的大小改變,那么就也會導致父View的重新measure、layout、draw()。