總述:
View有兩個很重要的方法:invalidate和requestLayout,常用於View重繪和更新。
Invalidate:
To farce a view to draw,call invalidate().——摘自View類源碼
從上面這句話看出,invalidate方法會執行draw過程,重繪View樹。
當View的appearance發生改變,比如狀態改變(enable,focus),背景改變,隱顯改變等,這些都屬於appearance范疇,都會引起invalidate操作。
所以當我們改變了View的appearance,需要更新界面顯示,就可以直接調用invalidate方法。
View(非容器類)調用invalidate方法只會重繪自身,ViewGroup調用則會重繪整個View樹。
RequestLayout:
To initiate a layout, call requestLayout(). This method is typically called by a view on itself when it believes that it can no longer fit within its current bounds.——摘自View源碼
從上面這句話看出,當View的邊界,也可以理解為View的寬高,發生了變化,不再適合現在的區域,可以調用requestLayout方法重新對View布局。
View執行requestLayout方法,會向上遞歸到頂級父View中,再執行這個頂級父View的requestLayout,所以其他View的onMeasure,onLayout也可能會被調用。
總結:
View繪制分三個步驟,順序是:onMeasure,onLayout,onDraw。經代碼親測,log輸出顯示:調用invalidate方法只會執行onDraw方法;調用requestLayout方法只會執行onMeasure方法和onLayout方法,並不會執行onDraw方法。
所以當我們進行View更新時,若僅View的顯示內容發生改變且新顯示內容不影響View的大小、位置,則只需調用invalidate方法;若View寬高、位置發生改變且顯示內容不變,只需調用requestLayout方法;若兩者均發生改變,則需調用兩者,按照View的繪制流程,推薦先調用requestLayout方法再調用invalidate方法。
相關知識點:
1.invalidate和postInvalidate:invalidate方法只能用於UI線程中,在非UI線程中,可直接使用postInvalidate方法,這樣就省去使用handler的煩惱。