渲染機(jī)制介紹
為了分析UI卡頓,我們有必要理解一下渲染機(jī)制,這套渲染機(jī)制適用于絕大部分的屏幕渲染,其中包括Android手機(jī)等眾多屏幕設(shè)備。
渲染的一些重要參數(shù):
屏幕刷新理想的頻率(硬件的角度):60Hz
理想的一秒內(nèi)繪制的幀數(shù),幀率(屏幕刷新的角度):60fps
這兩個(gè)參數(shù)都是理想值,指代的都是同一個(gè)概念。實(shí)際情況中難免會(huì)比它們低。在60fps內(nèi),系統(tǒng)會(huì)得到發(fā)送的VSYNC(垂直刷新/繪制)信號(hào)去進(jìn)行渲染,就會(huì)正常地繪制出我們需要的圖形界面。Android手機(jī)進(jìn)行繪制的時(shí)候,GPU幫助我們將UI組件等計(jì)算成紋理Texture和三維圖形Polygons,同時(shí)會(huì)使用OpenGL---會(huì)將紋理和Polygons緩存在GPU內(nèi)存里面。
其中,VSYNC:有兩個(gè)概念
Refresh Rate:屏幕在一秒時(shí)間內(nèi)刷新屏幕的次數(shù)----有硬件的參數(shù)決定,比如60HZ,即屏幕每秒刷新60次
Frame Rate:GPU在一秒內(nèi)繪制操作的幀數(shù),比如:60fps,
基本結(jié)論
要達(dá)到60fps,就要求:每一幀只能停留16ms。(大概就是1000ms/60 ~= 16ms刷新一次)

內(nèi)存抖動(dòng)是因?yàn)榇罅康膶?duì)象被創(chuàng)建又在短時(shí)間內(nèi)馬上被釋放。
?瞬間產(chǎn)生大量的對(duì)象會(huì)嚴(yán)重占用Young Generation的內(nèi)存區(qū)域,當(dāng)達(dá)到閥值,剩余空間不夠的時(shí)候,也會(huì)觸發(fā)GC。即使每次分配的對(duì)象占用了很少的內(nèi)存,但是他們疊加在一起會(huì)增加Heap的壓力,從而觸發(fā)更多其他類型的GC。這個(gè)操作有可能會(huì)影響到幀率,并使得用戶感知到性能問(wèn)題。
Android里面是一個(gè)三級(jí)Generation的內(nèi)存模型,最近分配的對(duì)象會(huì)存放在Young Generation區(qū)域,當(dāng)這個(gè)對(duì)象在這個(gè)區(qū)域停留的時(shí)間達(dá)到一定程度,它會(huì)被移動(dòng)到Old Generation,最后到Permanent Generation區(qū)域。

UI卡頓分析
Android每個(gè)16ms就會(huì)繪制一次Activity,通過(guò)上述的結(jié)論我們知道,如果由于一些原因?qū)е铝宋覀兊倪壿?、CPU耗時(shí)、GPU耗時(shí)大于16ms(應(yīng)用卡頓的根源就在于16ms內(nèi)不能完成繪制渲染合成過(guò)程,16ms需要完成視圖樹(shù)的所有測(cè)量、布局、繪制渲染及合成),UI就無(wú)法完成一次繪制,那么就會(huì)造成卡頓。
比如說(shuō),在16ms內(nèi),發(fā)生了頻繁的GC:
在第一個(gè)16ms內(nèi),UI正常地完成了繪制,那么屏幕不會(huì)卡頓。
在第二個(gè)16ms內(nèi),由于某些原因觸發(fā)了頻發(fā)的GC,UI無(wú)法在16ms內(nèi)完成繪制,就會(huì)卡頓。
UI卡頓外部和內(nèi)部常見(jiàn)原因
下面總結(jié)一些常見(jiàn)的UI卡頓原因:
?1.內(nèi)存抖動(dòng)的問(wèn)題
?2.方法太耗時(shí)了(CPU占用)
耗時(shí)原因分析
? ? 1)CPU計(jì)算時(shí)間,CPU的測(cè)量、布局時(shí)間
????2)CPU將計(jì)算好的Polygons和Texture傳遞到GPU的時(shí)候也需要時(shí)間。OpenGL ES API允許數(shù)據(jù)上傳到GPU后可以對(duì)數(shù)據(jù)進(jìn)行保存,緩存到display list。因此,我們平移等操作一個(gè)view是幾乎不怎么耗時(shí)的。
? ? 3)GPU進(jìn)行格柵化
當(dāng)我們的布局是用的FrameLayout的時(shí)候,我們可以把它改成merge,可以避免自己的幀布局和系統(tǒng)的ContentFrameLayout幀布局重疊造成重復(fù)計(jì)算(measure和layout)。
使用ViewStub:當(dāng)加載的時(shí)候才會(huì)占用。不加載的時(shí)候就是隱藏的,僅僅占用位置。
CPU優(yōu)化建議
針對(duì)CPU的優(yōu)化,從減輕加工View對(duì)象成Polygons和Texture來(lái)下手:
View Hierarchy中包涵了太多的沒(méi)有用的view,這些view根本就不會(huì)顯示在屏幕上面,一旦觸發(fā)測(cè)量和布局操作,就會(huì)拖累應(yīng)用的性能表現(xiàn)。那么我們就需要利用工具進(jìn)行分析。
如何找出里面沒(méi)用的view呢?或者減少不必要的view嵌套。
我們利用工具:Hierarchy Viewer進(jìn)行檢測(cè),優(yōu)化思想是:查看自己的布局,層次是否很深以及渲染比較耗時(shí),然后想辦法能否減少層級(jí)以及優(yōu)化每一個(gè)View的渲染時(shí)間。
我們打開(kāi)APP,然后打開(kāi)Android Device Monitor,然后切換到Hierarchy Viewer面板。除了看層次結(jié)構(gòu)之外,還可以看到一些耗時(shí)的信息:
三個(gè)圓點(diǎn)分別代表:測(cè)量、布局、繪制三個(gè)階段的性能表現(xiàn)。
1)綠色:渲染的管道階段,這個(gè)視圖的渲染速度快于至少一半的其他的視圖。
2)黃色:渲染速度比較慢的50%。
3)紅色:渲染速度非常慢。
GPU優(yōu)化建議
GPU優(yōu)化建議就是一句話:盡量避免過(guò)度繪制(overdraw)
一、背景經(jīng)常容易造成過(guò)度繪制。
手機(jī)開(kāi)發(fā)者選項(xiàng)里面找到工具:Debug GPU overdraw,其中,不同顏色代表了繪制了幾次:
