View的繪制從ActivityThread類中Handler的處理RESUME_ACTIVITY事件開始,在執(zhí)行performResumeActivity之后,創(chuàng)建Window以及DecorView并調(diào)用WindowManager的addView方法添加到屏幕上响蓉,addView又調(diào)用ViewRootImpl的setView方法谆趾,最終執(zhí)行performTraversals方法犹菇,依次執(zhí)行performMeasure妹懒,performLayout,performDraw野哭。也就是view繪制的三大過程在塔。
performMeasure會調(diào)用measure,measure又會調(diào)用onMeasure(),最終測量出view視圖的大小拨黔,還需要調(diào)用setMeasuredDimension方法設(shè)置測量的結(jié)果蛔溃,如果是ViewGroup需要調(diào)用measureChildren或者measureChild方法測量子view的大小從而計算自己的大小。
performLayout會調(diào)用layout篱蝇,layout又會調(diào)用onLayout(),從而計算出view擺放的位置贺待,View不需要實現(xiàn),通常由ViewGroup實現(xiàn)零截,在實現(xiàn)onLayout時可以通過getMeasuredWidth等方法獲取measure過程測量的結(jié)果進行擺放麸塞。
performDraw會調(diào)用draw,draw又會調(diào)用onDraw(),這個過程先是繪制背景涧衙,其次在onDraw()方法繪制view的內(nèi)容哪工,再然后調(diào)用dispatchDraw()調(diào)用子view的draw方法,最后繪制滾動條弧哎。ViewGroup默認不會執(zhí)行onDraw方法雁比,如果復(fù)寫了onDraw(Canvas)方法,需要調(diào)用 setWillNotDraw(false);清除不需要繪制的標記傻铣。
requestLayout()章贞、invalidate()與postInvalidate()有什么區(qū)別祥绞?
requestLayout():該方法會遞歸調(diào)用父窗口的requestLayout()方法非洲,直到觸發(fā)ViewRootImpl的performTraversals()方法,此時mLayoutRequestede為true蜕径,會觸發(fā)onMesaure()與onLayout()方法两踏,不一定會觸發(fā)onDraw()方法。
invalidate():該方法遞歸調(diào)用父View的invalidateChildInParent()方法兜喻,直到調(diào)用ViewRootImpl的invalidateChildInParent()方法梦染,最終觸發(fā)ViewRootImpl的performTraversals()方法,此時mLayoutRequestede為false,不會觸發(fā)onMesaure()與onLayout()方法帕识,當時會觸發(fā)onDraw()方法泛粹。
postInvalidate():該方法功能和invalidate()一樣,只是它可以在非UI線程中調(diào)用肮疗。
一般說來需要重新布局就調(diào)用requestLayout()方法晶姊,需要重新繪制就調(diào)用invalidate()方法。