android的构成和工作流程,分析Android中View的工作流程
8種機械鍵盤軸體對比
本人程序員,要買一個寫代碼的鍵盤,請問紅軸和茶軸怎么選?
在分析View的工作流程時,需要先分析一個很重要的類,MeasureSpec。這個類在View的測量(Measure)過程中會用到。
MeasureSpec
MeasureSpec是View的靜態內部類,可以理解為是一種測量規格,是一個32位int值,高2位代表SpecMode,低30位代表SpecSize,SpecMode是指測量模式,而SpecSize是指在某種測量模式下的規格大小。
SpecMode有三種模式,分別為:UNSPECIFIED:父容器不對View做限制
EXACTLY:父容器已經檢測出View所需的精確大小,View的大小為SpecSize中指定的值。
AT_MOST:父容器指定了一個SpecSize,View的大小不大大于該值。
MeasureSpec與LayoutParams
系統通過MeasureSpec作為測量規格,對View進行測量,但在設置View的寬高時,都是通過LayoutParams,因此系統在測量View的時候,會將LayoutParams在父容器的約束下轉換成MeasureSpec,然后根據確定的MeasureSepc得到View測量后的寬高。有幾點需要說明:LayoutParams和父容器一起確定MeasureSpec;
對于DecorView,其MeasureSpec是由窗口的尺寸和自身的LayoutParams共同確定的;由于窗口尺寸是確定的,因此主要與DecorView自身的LayoutParams有關,具體的對應關系如下圖描述:
對于普通View,其MeasureSpec是由父容器的MeasureSpec和自身的LayoutParams共同確定的。其對應關系如下圖描述:
對普通View,簡單總結一下:當View采用固定寬/高的時候,不管父容器的MeasureSpec是什么,View的MeasureSpec都是精確模式并且其大小遵循Layoutparams中的大小。
當View的寬/高是match_parent時,如果父容器的模式是精準模式,那么View也是精準模式并且其大小是父容器的剩余空間;如果父容器是最大模式,那么View也是最大模式并且其大小不會超過父容器的剩余空間。
當View的寬/高是wrap_content時,不管父容器的模式是精準還是最大模式,View的模式總是最大模式并且大小不能超過父容器的剩余空間。
在UNSPECIFIED模式中,系統內部會進行多次Measure過程,才能確定View的寬高。
View的工作流程
ViewRoot是連接WindowManager與DecorView的紐帶,View的繪制流程都是通過ViewRoot來完成的。
View的工作流程是從ViewRoot的performTraversals方法開始的,它經過measure、layout和draw三個過程才能最終將一個View繪制出來,其中measure用來測量View的寬和高,layout用來確定View在父容器中的放置位置,而draw則負責將View繪制在屏幕上。用一張圖來描述View的工作過程:
View的測量(Measure)過程
在View的Measure過程中,完成對View的測量,確定View的寬高。ViewRoot中的performTraversals()會依次調用ViewRoot中的performMeasure()、performLayout()和performDraw()三個方法,這三個方法分別完成頂級View的measure、layout和draw這三大流程。其中在performMeasure()中會調用View的measure()方法,在measure()方法中又會調用onMeasure()方法。在onMeasure()中將View寬/高的測量值傳給setMeasuredDimension()方法,完成View的測量過程。
對于ViewGroup來說,除了完成自己的measure過程以外,還會遍歷去調用所有子元素的measure()方法,各個子元素再遞歸去執行這個過程。和View不同的是,ViewGroup是一個抽象類,因此它沒有重寫View的onMeasure方法,因為不同的ViewGroup子類有不同的布局特性,這導致它們的測量細節各不相同。在ViewGroup的onMeasure()中最后也會調用setMeasuredDimension()方法,完成測量過程。
measure完成以后,通過getMeasuredWidth()/Height()方法就可以正確地獲取到View的測量寬/高。需要注意的是,在某些極端情況下,系統可能需要多次measure才能確定最終的測量寬/高,在這種情形下,在onMeasure方法中拿到的測量寬/高很可能是不準確的。一個比較好的習慣是在onLayout方法中去獲取View的測量寬/高或者最終寬/高。
View的布局(Layout)過程
Layout的作用是ViewGroup用來確定子元素的位置,ViewRoot中的performLayout()中會調用View的layout()方法,在layout()方法中onLayout()方法又會被調用。onLayout的具體實現同樣和具體的布局有關,所以View和ViewGroup均沒有真正實現onLayout方法。
當ViewGroup的位置被確定后,它在onLayout()中會遍歷所有的子元素并調用其layout()方法,layout()方法確定View本身的位置,而onLayout()方法則會確定所有子元素的位置。
View的繪制(Draw)過程
Draw的作用是將View繪制到屏幕上面。View的繪制過程遵循如下幾步:繪制背景background.draw(canvas)
繪制自己(onDraw)
繪制children(dispatchDraw)
繪制裝飾(onDrawScrollBars)
View繪制過程的傳遞是通過dispatchDraw來實現的,dispatchDraw會遍歷調用所有子元素的draw方法,如此draw事件就一層層地傳遞了下去。
參考文獻
[1] 任玉剛.Android開發藝術探索[M].電子工業出版社, 2015.9:1 - 507
總結
以上是生活随笔為你收集整理的android的构成和工作流程,分析Android中View的工作流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 程序类图,Android
- 下一篇: 荣耀v30pro搭载鸿蒙吗,荣耀麒麟30