一般情況
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()用爪。