# 引子
- 今天在研究使用HierarchyViewer工具
- 打開ViewHierarchy,選擇一個Activity的,選中某個View,選擇工具中的Show Extras選項
- 觀察單個view,選擇單個view后會出現如下圖所示圖形。這里會看到Measure、Layout、Draw的耗時,查了下這里的三個參數,牽扯的知識挺廣,其中還有有個**60fps**的概念也是比較重要。
?
- 如果無法出現上面的耗時統計點擊菜單 Profile Node,重新加載之后就有了
# View
- Android界面上,View才是真正的顯示視圖
View 包含兩種, View和ViewGroup,這種關系就像Java awt編程中的Component和Container,即ViewGroup是一種View,但里面又可以容納View和另外的ViewGroup
- View 的直接子類:Widget(就是各種控件,比如 - Button)
- ViewGroup 的直接子類:Layout(也就對應于Android的六大布局組件,Relative,Table,Absolute,Frame,Grid和Linear)
Activity
- 并不是顯示視圖的容器,而是控制單元(提供交互)
**Activity的生命周期,那些回調函數(oncreate,onstart這些)是用來控制頁面的交互效果**
# Window
- 真正的顯示視圖容器
每個Activity在構造的時候,會初始化一個Window(PhoneWindow,可以通過getWindow()方法拿到),每個Window對應一個DecorView(實際上是一個ViewGroup,可以往里添加東西)
setContentView()方法,其實是來自于**PhoneWindow**
# 那么它們到底是怎么協調工作的呢?
- layout里的xml布局文件為原料
LayoutInflater.inflate()方法,用來實例化xml文件為view對象
我們看到的setContentView(R.layout.main)方法,寫完整了其實應該長這樣:getWindow().setContentView(LayoutInflater.from(this).inflate(R.layout.main,null))
# 幀(Frame)
- 我們看到的動畫效果,其實是由很多個圖片快速、連續顯示造成的,每一幅圖片就是一幀
- FPS(frames per second)不是DPS(每秒造成的傷害),而是每秒渲染了多少幀
- Hz:一般用來指屏幕刷新頻率
- 普通電影的FPS是24,是考慮到了制作成本。FPS達到30時,畫面會顯得平滑連續。Android屏幕刷新列率為60Hz,相應的,**FPS應該也要達到60**, 小了會卡頓,大了會畫面撕裂
既然每秒要加載60幀,那么每一幀的渲染時間應該為 1000/60 = 16.67 (ms)
那么什么因素可能會導致16.67ms內完不成一幀的渲染呢?
- 手機太low,CPU + GPU合力工作效率低下,這個過程涉及到CPU將圖形計算為多邊形,在交由GPU去柵格化(Rasterization)
橫豎屏切換,需要用savedInstanceState保存的view信息進行重畫
- 動畫效果太多
GC太多(Dalvik虛擬機 10~20 ms,改進為ART之后雖降低到2~3ms,但也會影響)
- UI線程阻塞(Android 4.0 之后加入了render thread來減輕UI線程負擔)
界面試圖結構過于復雜(可以通過Hierachy View查看)
- 過度繪制,**打開手機開發中調試里面開啟GPU渲染**

?
- 繪制顏色的標識,從好到差:藍色(1x次繪制),淺綠色(2x繪制),淡紅色(3x繪制),紅色(4x繪制)。
- 當然這也只能看到大概的繪制效果,如果想知道更詳細的控件分析呢,那么可以使用**Systrace**來分析,下篇開開始學習
## 其他參考
- [主要原文](https://testerhome.com/topics/4441)
- [如何測量Android應用的幀率FPS和統計](http://jingyan.baidu.com/article/ac6a9a5e7e5f352b653eacfa.html)
- 簡單的測量fps
- adb shell dumpsys gfxinfo "你自己的應用名字" > fps.txt