前言
本篇文章是《深入理解Android布局優(yōu)化》系列文章的第二篇。系列的主要目的是希望將Android開發(fā)中涉及布局優(yōu)化的部分做一次系統(tǒng)的歸納、總結(jié)和學(xué)習(xí)。本系列文章包含理論基礎(chǔ)、常見工具、項(xiàng)目實(shí)踐三個(gè)部分。
理論基礎(chǔ):「深入理解Android布局優(yōu)化 1」-布局的加載流程與繪制原理,主要講解布局的加載流程與繪制原理,從源碼上發(fā)現(xiàn)布局的性能瓶頸。
常見工具:「深入理解Android布局優(yōu)化 2」-常見工具的使用,主要講解Android布局優(yōu)化時(shí)各種常見工具的使用。
項(xiàng)目實(shí)踐:以一個(gè)實(shí)際的APP為例,將學(xué)習(xí)到的理論和工具,實(shí)際運(yùn)用到Android開發(fā)中。
本文中實(shí)踐時(shí)使用的項(xiàng)目地址:https://github.com/linux-link/Fan,可以先閱讀這篇文章了解這個(gè)項(xiàng)目一次組件化與Android Jetpack的實(shí)踐
本篇屬于三個(gè)部分中的常見工具部分。
目錄
- 工具集
- GPU過(guò)度繪制
- 渲染耗時(shí)
- Layout Inspector
- Choreographer
- Systrace
- Matrix
- 總結(jié)
正文
一、工具集
在Android的布局優(yōu)化中也有大量的工具可供選擇,這里整理了一些常用且易于上手的工具,如下所示
| 工具 | 能力 | 上手難度 |
|---|---|---|
| GPU過(guò)度繪制 | 發(fā)現(xiàn)布局過(guò)度嵌套 | 低 |
| GPU呈現(xiàn)模式分析 | 統(tǒng)計(jì)布局繪制耗時(shí) | 低 |
| Layout Inspector | 列出布局樹 | 中 |
| Choreographer | 統(tǒng)計(jì)界面的FPS | 中 |
| Systrace | 統(tǒng)計(jì)進(jìn)程的內(nèi)核信息 | 高 |
| Matrix | 全方位發(fā)現(xiàn)Android中的性能問題 | 高 |
二、GPU過(guò)度繪制
過(guò)度繪制(Overdraw)描述的是屏幕上的某個(gè)像素在同一幀的時(shí)間內(nèi)被繪制了多次。在多層次的UI結(jié)構(gòu)里面, 如果不可見的UI也在做繪制的操作,這就會(huì)導(dǎo)致某些像素區(qū)域被繪制了多次。這就浪費(fèi)大量的CPU以及GPU資源。
- 藍(lán)色: 代表1層覆蓋。像素繪制了兩次。大片的藍(lán)色還是可以接受的,若整個(gè)窗口是藍(lán)色的,可以擺脫一層。
- 綠色: 代表2層覆蓋。像素繪制了三次。中等大小的綠色區(qū)域是可以接受的但你應(yīng)該嘗試優(yōu)化、減少它們。
- 淡紅: 代表3層覆蓋倍。像素繪制了四次,小范圍可以接受。
- 深紅: 代表4層覆蓋。像素繪制了五次或者更多。
以MIUI系統(tǒng)為例,展示如何打開GPU過(guò)度繪制,更多設(shè)置 -> 開發(fā)者選項(xiàng) -> 調(diào)試GPU過(guò)度繪制 -> 顯示過(guò)度繪制區(qū)域。
理論上來(lái)說(shuō)深紅色的區(qū)域是需要重點(diǎn)優(yōu)化的對(duì)象,我們需要盡可能減少過(guò)度繪制,不過(guò)在實(shí)際項(xiàng)目中需要根據(jù)開發(fā)的具體情況來(lái)靈活判斷。
三、GPU呈現(xiàn)模式分析
渲染耗時(shí)顧名思義就是APP的界面在渲染過(guò)程中消耗的時(shí)間,在Android中每一楨的渲染耗時(shí)控制在16ms以內(nèi),則不會(huì)產(chǎn)生卡頓的感覺。
以MIUI系統(tǒng)為例,展示如何查看渲染耗時(shí)。選擇更多設(shè)置->開發(fā)者選項(xiàng)->GPU呈現(xiàn)模式分析->在屏幕上顯示為條形圖
開啟之后,在手機(jī)中查看任意界面,界面上都會(huì)滾動(dòng)顯示垂直的柱狀圖來(lái)表示每幀畫面所需要渲染的時(shí)間,柱狀圖越高表示花費(fèi)的渲染時(shí)間越長(zhǎng)。如圖所示
從Android 6.0之后每一楨的繪制大致有個(gè)8個(gè)步驟:
-
Swap Buffers
表示處理任務(wù)的時(shí)間,也可以說(shuō)是CPU等待GPU完成任務(wù)的時(shí)間,線條越高,表示GPU做的事情越多;
-
Command Issue
表示執(zhí)行任務(wù)的時(shí)間,這部分主要是Android進(jìn)行2D渲染顯示列表的時(shí)間,為了將內(nèi)容繪制到屏幕上,Android需要使用Open GL ES的API接口來(lái)繪制顯示列表,紅色線條越高表示需要繪制的視圖更多;
-
Sync & Upload
表示的是準(zhǔn)備當(dāng)前界面上有待繪制的圖片所耗費(fèi)的時(shí)間,為了減少該段區(qū)域的執(zhí)行時(shí)間,我們可以減少屏幕上的圖片數(shù)量或者是縮小圖片的大?。?/p>
-
Draw
表示測(cè)量和繪制視圖列表所需要的時(shí)間,藍(lán)色線條越高表示每一幀需要更新很多視圖,或者View的onDraw方法中做了耗時(shí)操作;
-
Measure/Layout
表示布局的onMeasure與onLayout所花費(fèi)的時(shí)間,一旦時(shí)間過(guò)長(zhǎng),就需要仔細(xì)檢查自己的布局是不是存在嚴(yán)重的性能問題;
-
Animation
表示計(jì)算執(zhí)行動(dòng)畫所需要花費(fèi)的時(shí)間,包含的動(dòng)畫有ObjectAnimator,ViewPropertyAnimator,Transition等等。一旦這里的執(zhí)行時(shí)間過(guò)長(zhǎng),就需要檢查是不是使用了非官方的動(dòng)畫工具或者是檢查動(dòng)畫執(zhí)行的過(guò)程中是不是觸發(fā)了讀寫操作等等;
-
Input Handling
表示系統(tǒng)處理輸入事件所耗費(fèi)的時(shí)間,粗略等于對(duì)事件處理方法所執(zhí)行的時(shí)間。一旦執(zhí)行時(shí)間過(guò)長(zhǎng),意味著在處理用戶的輸入事件的地方執(zhí)行了復(fù)雜的操作;
-
Misc Time/Vsync Delay
表示在主線程執(zhí)行了太多的任務(wù),導(dǎo)致UI渲染跟不上vSync的信號(hào)而出現(xiàn)掉幀的情況;
四、Layout Inspector
關(guān)于Layout Inspector的使用,google的官方中文文檔說(shuō)的非常詳細(xì),強(qiáng)烈推薦仔細(xì)閱讀,以下內(nèi)容節(jié)選自官方文檔,更多更詳細(xì)的內(nèi)容,請(qǐng)仔細(xì)閱讀官方文檔使用 Layout Inspector 調(diào)試布局。
利用 Android Studio 中的布局檢查器,可以在運(yùn)行時(shí)從 Android Studio IDE 內(nèi)檢查自己應(yīng)用的視圖層次結(jié)構(gòu)。 如果布局在運(yùn)行時(shí)(而不是完全在 XML 中)構(gòu)建并且布局沒有按預(yù)期顯示,這種檢查將非常有用。
按以下步驟操作,打開布局檢查器:
在連接的設(shè)備或模擬器上運(yùn)行您的應(yīng)用。
點(diǎn)擊Tools > Android > Layout Inspector。
-
在出現(xiàn)的Choose Process對(duì)話框中,選擇您想要檢查的應(yīng)用進(jìn)程,然后點(diǎn)擊OK。
Choose Process 對(duì)話框默認(rèn)情況下,Choose Process對(duì)話框僅會(huì)為 Android Studio 中當(dāng)前打開的項(xiàng)目列出進(jìn)程,并且該項(xiàng)目必須在設(shè)備上運(yùn)行。 如果您想要檢查設(shè)備上的其他應(yīng)用,請(qǐng)點(diǎn)擊Show all processes。 如果您正在使用已取得 root 權(quán)限的設(shè)備或者沒有安裝 Google Play 商店的模擬器,那么您會(huì)看到所有正在運(yùn)行的應(yīng)用。 否則,您只能看到可以調(diào)試的運(yùn)行中應(yīng)用。
布局檢查器會(huì)捕獲快照,將它保存為.li文件并打開。 如圖 2 中所示,布局檢查器將顯示以下內(nèi)容:
- View Tree:視圖在布局中的層次結(jié)構(gòu)。
- Screenshot:帶每個(gè)視圖可視邊界的設(shè)備屏幕截圖。
-
Properties Table:選定視圖的布局屬性。
布局檢查器
可以在View Tree中點(diǎn)擊視圖以在屏幕截圖中選擇相同視圖,反之亦然。 視圖的所有布局屬性都將顯示在Properties Table中。
如果布局包括重疊視圖,則默認(rèn)情況下,只有前面的視圖可以在屏幕截圖中點(diǎn)擊。 要讓后面的視圖可以在屏幕截圖中點(diǎn)擊,請(qǐng)執(zhí)行以下操作: 在View Tree中右鍵點(diǎn)擊前面的視圖,然后取消選中Show in preview。 此操作不會(huì)讓視圖內(nèi)容消失;僅會(huì)讓屏幕截圖中的可點(diǎn)擊邊界消失,以便您可以點(diǎn)擊在它后面的視圖。
如果設(shè)備上的布局發(fā)生變化,布局檢查器不會(huì)更新。 必須再次點(diǎn)擊Tools > Android > Layout Inspector,創(chuàng)建一個(gè)新的快照。每一個(gè)快照都將保存到project-name/captures/內(nèi)一個(gè)單獨(dú)的.li文件中。
五、Choreographer
上面介紹的幾種檢測(cè)方式只適合線下使用,如果我們需要在線上獲取已經(jīng)發(fā)布APP的卡頓情況,則適合使用Choreographer。
通過(guò) Choreographer.getInstance().postFrameCallback(),可以獲得當(dāng)前的界面的FPS,通過(guò)檢查一段時(shí)間內(nèi)的FPS值,我們就可以得知當(dāng)前界面是否發(fā)生了卡頓。
private static final long MONITOR_INTERVAL = 1600L; //單次計(jì)算FPS使用1600毫秒
private static final long MONITOR_INTERVAL_NANOS = MONITOR_INTERVAL * 1000L * 1000L;//顯示fps的間隔時(shí)間,1.6秒
private static final long MAX_INTERVAL = 1000L; //設(shè)置計(jì)算fps的單位時(shí)間間隔1000ms,即fps/s;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(flipView);
Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
if (lastFrameTime == 0) {
lastFrameTime = frameTimeNanos;
}
long interval = frameTimeNanos - lastFrameTime;
if (interval > MONITOR_INTERVAL_NANOS) {
double fps = (((double) (frameCount * 1000L * 1000L)) / interval) * MAX_INTERVAL;
Log.e("fps:", fps + "");
frameCount = 0;
lastFrameTime = 0;
} else {
++frameCount;
}
Choreographer.getInstance().postFrameCallback(this);
}
});
}
2019-06-28 22:10:18.918 24460-24460/com.link.flipview E/fps:: 61.04245124020559
2019-06-28 22:10:19.098 24460-24460/com.link.flipview E/fps:: 61.04702584262233
2019-06-28 22:10:19.278 24460-24460/com.link.flipview E/fps:: 61.047967231502405
2019-06-28 22:10:19.459 24460-24460/com.link.flipview E/fps:: 61.04632000634784
2019-06-28 22:10:19.639 24460-24460/com.link.flipview E/fps:: 61.04324641755805
2019-06-28 22:10:19.819 24460-24460/com.link.flipview E/fps:: 61.046939755064415
2019-06-28 22:10:19.999 24460-24460/com.link.flipview E/fps:: 61.050491907012486
2019-06-28 22:10:20.179 24460-24460/com.link.flipview E/fps:: 61.042186309896735
2019-06-28 22:10:20.360 24460-24460/com.link.flipview E/fps:: 61.04657118380607
2019-06-28 22:10:20.541 24460-24460/com.link.flipview E/fps:: 61.048108852294455
六、Systrace
Systrace是Android性能優(yōu)化時(shí)非常常用的工具,它可以記錄短時(shí)間內(nèi)的設(shè)備活動(dòng)情況,并生成一份Android內(nèi)核中的數(shù)據(jù)報(bào)告,例如CPU調(diào)度程序,磁盤活動(dòng)和應(yīng)用程序線程等等。
Systrace生成的報(bào)告如圖所示:
此報(bào)告提供了Android設(shè)備在給定時(shí)間段內(nèi)的系統(tǒng)進(jìn)程的總體情況。該報(bào)告還檢查捕獲的跟蹤信息,以突出顯示它所觀察到的問題,例如UI jank或高功耗。
注意:Systrace工具不會(huì)收集有關(guān)應(yīng)用程序進(jìn)程中代碼執(zhí)行的信息。有關(guān)應(yīng)用程序正在執(zhí)行的方法以及它使用的CPU資源的更多詳細(xì)信息,請(qǐng)使用Android Studio中的CPU分析器。您還可以 使用CPU Profiler 生成跟蹤日志并導(dǎo)入和檢查它們。
Systrace指南
要了解有關(guān)Systrace工具的更多信息,請(qǐng)參閱以下官方指南,或者閱讀這篇官方文檔的譯文:https://www.cnblogs.com/andy-songwei/p/10659564.html
-
定義可以傳遞到Systrace命令行界面的不同選項(xiàng)和標(biāo)志。
-
說(shuō)明如何在Android9或更高版本的設(shè)備上直接捕獲systrace。
-
解釋systrace的報(bào)告,以及瀏覽報(bào)告時(shí)常用快捷鍵,并描述如何識(shí)別性能問題。
-
描述如何在代碼中使用自定標(biāo)簽,讓systrace更簡(jiǎn)單易用。
-
提高游戲性能(Improve your game's performance)
描述如何使用Systrace工具改進(jìn)游戲中的特定性能區(qū)域,包括幀速率一致性,功耗和渲染平滑度。
七、Matrix
Matrix 是一款微信研發(fā)并日常使用的應(yīng)用性能接入框架,支持iOS, macOS和Android。 Matrix 通過(guò)接入各種性能監(jiān)控方案,對(duì)性能監(jiān)控項(xiàng)的異常數(shù)據(jù)進(jìn)行采集和分析,輸出相應(yīng)的問題分析、定位與優(yōu)化建議,從而幫助開發(fā)者開發(fā)出更高質(zhì)量的應(yīng)用。
Matrix-android 當(dāng)前監(jiān)控范圍包括:應(yīng)用安裝包大小,幀率變化,啟動(dòng)耗時(shí),卡頓,慢方法,SQLite 操作優(yōu)化,文件讀寫,內(nèi)存泄漏等等。
APK Checker: 針對(duì) APK 安裝包的分析檢測(cè)工具,根據(jù)一系列設(shè)定好的規(guī)則,檢測(cè) APK 是否存在特定的問題,并輸出較為詳細(xì)的檢測(cè)結(jié)果報(bào)告,用于分析排查問題以及版本追蹤
Resource Canary: 基于 WeakReference 的特性和 Square Haha 庫(kù)開發(fā)的 Activity 泄漏和 Bitmap 重復(fù)創(chuàng)建檢測(cè)工具
Trace Canary: 監(jiān)控界面流暢性、啟動(dòng)耗時(shí)、頁(yè)面切換耗時(shí)、慢函數(shù)及卡頓等問題
SQLite Lint: 按官方最佳實(shí)踐自動(dòng)化檢測(cè) SQLite 語(yǔ)句的使用質(zhì)量IO Canary: 檢測(cè)文件 IO 問題,包括:文件 IO 監(jiān)控和 Closeable Leak 監(jiān)控
關(guān)于Matrix就簡(jiǎn)單介紹到這里,更多更詳細(xì)的資料以及使用幫助請(qǐng)查閱官方文檔:
https://github.com/Tencent/matrix#matrix_cn
八、總結(jié)
本篇文章梳理了6種不同的UI優(yōu)化工具,這些工具中大多都比較常用,其中比較重要的有Layout Inspector和Systrace,Matrix因?yàn)樾枰氲谌娇蚣?,在?shí)際項(xiàng)目可以根據(jù)需要決定是否使用。下一篇將以一個(gè)《飯fan》的源碼為例,通過(guò)運(yùn)用這三種工具來(lái)發(fā)現(xiàn)、解決項(xiàng)目中性能問題。