1. Android繪制原理及工具選擇
1.1 繪制分析
CPU:負責(zé)計算顯示內(nèi)容抬虽。視圖的創(chuàng)建略号,布局計算刑峡,圖片解碼,文本繪制璃哟。
GPU:負責(zé)柵格化操作(UI元素繪制到屏幕上)氛琢,Button拆分成像素。換算成紋理随闪。
16ms 發(fā)出VSync信號出發(fā) UI 渲染阳似。
大多數(shù)的Android設(shè)備屏幕刷新頻率:60HZ
1.2 優(yōu)化工具
Systrace
關(guān)注Frames
正常:綠色圓點,丟幀:黃色或紅色
Alerts欄铐伴。自動分析異常性能分析的一些條目
Layout Inspector
查看視圖層次結(jié)構(gòu)
Choreographer(API16以后)
獲取FPS撮奏,線上使用,具備實時性
Choreographer.getInstance().postFrameCallback
2. Android布局加載原理
深入布局加載源碼:
setContentView -> LayoutInflater -> inflate -> getLayout -> createViewFromTag -> Factory -> createView -> 反射
性能瓶頸
布局文件解析:IO過程当宴。布局特別大畜吊,文件也就特別大,io也就會卡頓户矢。
創(chuàng)建View對象:反射玲献。反射使用過多(標(biāo)簽過多)導(dǎo)致反射很慢。
LayoutInflater.Factory
LayoutInflater 創(chuàng)建View的一個Hook
定制創(chuàng)建View的過程:全局替換自定義TextView等
LayoutInflater當(dāng)中的 Factory與Factory2
Factory2繼承于Factory
多了一個參數(shù):parent
3. 優(yōu)雅獲取界面布局耗時
3.1 常規(guī)方式
獲取每個界面的加載耗時梯浪。
實現(xiàn):復(fù)寫setContentView捌年、手動埋點。不夠優(yōu)雅挂洛,代碼有侵入性礼预。
3.2 AOP/ArtHook
找到切面點。切Activity的setContentView虏劲。
@Around("execution(* android.app.Activity.setContentView(..))")
call表示切在方法調(diào)用的部分托酸。execution表示切在方法的里面
獲取任一控件的加載耗時 褒颈,在內(nèi)部和執(zhí)行方法處和啟動時間計算方式一致儿捧。
低侵入性敏簿。
LayoutInflater.Factory
3.3 異步Inflate實戰(zhàn)
布局文件讀取過程慢兼都,IO過程
創(chuàng)建view過程慢生巡,反射過程創(chuàng)建璃俗,比new慢3倍冕臭。
根本性解決滚局。不使用反射/IO
側(cè)面緩解工猜。
AsyncLayoutInflater(異步Inflater)
- WorkThread加載布局
- 回調(diào)主線程
- 節(jié)約主線程時間
導(dǎo)包:
com.android.support:asynclayoutinflater
4. 布局加載優(yōu)化實戰(zhàn)
AsyncLayoutInflater只是緩解摊趾。
Java代碼寫布局币狠,它的缺點是不便于開發(fā)、可維護性差砾层。
X2C框架(通過APT編譯器翻譯XML為Java代碼)
開發(fā)人員寫XML漩绵,加載Java代碼。
annotationProcessor 'com.zhangyue.we:x2c-apt:1.1.2'
implementation 'com.zhangyue.we:x2c-lib:1.0.6'
用到的頁面使用:@Xml(layouts = "activity_main")
問題:部分屬性Java不支持肛炮、失去了系統(tǒng)的兼容(AppCompat)
5. 視圖繪制優(yōu)化實戰(zhàn)
優(yōu)化布局層級及復(fù)雜度
測量:確定大小
布局:確定位置
繪制:繪制視圖
性能瓶頸:每個階段耗時止吐。自頂向下遍歷。觸發(fā)多次侨糟。
準(zhǔn)則:減少View樹層級碍扔。
寬而淺,避免窄而深
(布局層級 從上往下叫寬度秕重,所有元素盡可能在一個ViewGroup當(dāng)中)
(布局深度盡可能更淺)
1)ConstrainLayout:實現(xiàn)幾乎完全扁平化布局不同。構(gòu)建復(fù)雜布局性能更高。具有RelativeLayout和LinearLayout的特性
2)不嵌套使用RelativeLayout
3)不在嵌套LinearLayout中使用weight
4)merge標(biāo)簽:減少一個層級溶耘,只能用于根View
過度繪制
一個像素最好只會被控制一次二拐。
5)調(diào)試GPU過度繪制(開發(fā)者模式中打開)
藍色可接受
避免過度繪制方法
6)去掉多余背景色,減少復(fù)雜shape使用
7)避免層級疊加
8)自定義View使用 clipRect 屏蔽被遮蓋View繪制
9)ViewStub:高效占位符凳兵、延遲初始化
10)onDraw中避免:創(chuàng)建大對象百新、耗時操作。
11)TextView優(yōu)化
6. 總結(jié)
用到了哪些工具庐扫?
結(jié)構(gòu)化思維饭望。使用了很多工具,有不同的使用場景形庭。
1)Choreographer 可以帶到線上杰妓,得到幀率。
2)每個布局耗時 AOP碘勉、HOOK
3)線下開發(fā)環(huán)節(jié)、Systrace桩卵、Layout Inspector
4)布局為什么會導(dǎo)致卡頓验靡,你又是如何優(yōu)化的倍宾?
5)IO、反射胜嗓、遍歷高职、重繪
6)異步Inflate、X2C辞州、減少層級怔锌、重繪
7)AOP、監(jiān)控
8)做完布局優(yōu)化后有哪些成果產(chǎn)出变过?
9)體系化監(jiān)控手段:線下 + 線上
指標(biāo):FPS埃元、加載時間、布局層級
核心路徑保障