Android效能優化:手把手帶你全面瞭解 繪製優化
阿新 • • 發佈:2019-02-05
前言
- 在
Android
開發中,效能優化策略十分重要 - 本文主要講解效能優化中的繪製優化,希望你們會喜歡。
目錄
1. 影響的效能
繪製效能的好壞 主要影響 :Android
應用中的頁面顯示速度
2. 如何影響效能
繪製影響Android
效能的實質:頁面的繪製時間
1個頁面通過遞迴 完成測量 & 繪製過程
3. 優化思路
主要優化方向是:
- 降低
View.onDraw()
的複雜度 - 避免過度繪製
(Overdraw)
4. 具體優化方案
- 具體如下
- 下面,我將詳細分析每種優化方案
4.1. 降低View.onDraw()的複雜度
4.1.1 onDraw()中不要建立新的區域性物件
4.1.2 避免onDraw()執行大量 & 耗時操作
4.2 避免過度繪製(Overdraw)
4.2.1 過度繪製的簡介
4.2.2 過度繪製的表現形式
過度繪製 會導致螢幕顯示的色塊不同,具體如下
附:示例說明
4.2.3 過度繪製的優化原則
很多 過度繪製是難以避免的,如 上述例項的 文字 & 背景導致的過度繪製;只能儘可能避免過度繪製:
1. 儘可能地控制 過度繪製的次數 = 2
次(綠色)以下,藍色最理想
2. 儘可能避免 過度繪製的粉色 & 紅色情況
3. 不允許 3 次以上的過度繪製(淡紅色)面積 超過 螢幕大小的 1/4
4.2.4 優化方案
- 移除預設的
Window
背景 - 移除 控制元件中不必要的背景
- 減少佈局檔案的層級(巢狀)
- 自定義控制元件View優化:使用 clipRect() 、 quickReject()
優化方案1: 移除預設的 Window 背景
- 背景
一般應用程式 預設 繼承的主題 =windowBackground
,如預設的 Light 主題:
<style name="Theme.Light">
<item name="isLightTheme">true</item>
<item name="windowBackground" >@drawable/screen_background_selector_light</item>
...
</style>
問題
一般情況下,該預設的 Window 背景基本用不上:因背景都自定義設定
若不移除,則導致所有介面都多 1 次繪製解決方案
移除預設的 Window 背景
// 方式1:在應用的主題中新增如下的一行屬性
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 或者 -->
<item name="android:windowBackground">@null</item>
// 方式2:在 BaseActivity 的 onCreate() 方法中使用下面的程式碼移除
getWindow().setBackgroundDrawable(null);
<!-- 或者 -->
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
優化方案2:移除 控制元件中不必要的背景
如2個常見場景:
- 場景1:
ListView
與Item
列表頁(ListView)
與 其內子控制元件(Item)
的背景相同 = 白色,故可移除子控制元件(Item)
佈局中的背景
- 場景2:
ViewPager
與Fragment
對於1個ViewPager
+ 多個Fragment
組成的首頁介面,若每個
Fragment
都設有背景色,即 ViewPager 則無必要設定,可移除
關於更多場景,可使用工具 Hierarchy View
檢視,具體請看文章: 過渡繪製的使用工具:Hierarchy View
優化方案3:減少佈局檔案的層級(減少不必要的巢狀)
- 原理:減少不必要的巢狀 ->> UI層級少 ->> 過度繪製的可能性低
- 優化方式:使用佈局標籤
<merge>
& 合適選擇佈局型別
具體請看文章:
優化方案4:自定義控制元件View優化:使用 clipRect() 、 quickReject()
clipRect()
- 作用:給 Canvas 設定一個裁剪區域,只有在該區域內才會被繪製,區域之外的都不繪製
- 例項說明:
DrawerLayout
佈局 = 左抽屜佈局
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTim
// ...僅貼出關鍵程式碼
// 1. 遍歷 DrawerLayout 的 child view,拿到抽屜佈局
for (int i = 0; i < childCount; i++) {
final View v = getChildAt(i);
if (v == child || v.getVisibility() != VISIBLE
|| !hasOpaqueBackground(v) || !isDrawerView(v)
|| v.getHeight() < height) {
continue;
}
// a. 若是左抽屜佈局
// 則取抽屜佈局的右邊界作為裁剪區的左邊界、設定原主佈局的裁剪區域,如上圖裁剪區域
if (checkDrawerViewAbsoluteGravity(v, Gravity.LEFT)) {
final int vright = v.getRight();
if (vright > clipLeft) clipLeft = vright;
// b. 若是右抽屜佈局
// 則取抽屜佈局的左邊界作為裁剪區的右邊界、設定原主佈局的裁剪區域
} else {
final int vleft = v.getLeft();
if (vleft < clipRight) clipRight = vleft;
}
}
// 2. 通過clipRect()設定原主佈局的顯示範圍 = 裁剪區域,使其僅在上圖中的紅框區域(即不阻礙抽屜佈局的區域)顯示
// 從而避免過度繪製
canvas.clipRect(clipLeft, 0, clipRight, getHeight());
}
......
}
quickreject()
- 作用:判斷和某個矩形相交
- 具體措施:若判斷與矩形相交,則可跳過相交的區域,從而減少過度繪製
4.4 其他優化方案
總結
至此,關於繪製優化的方案講解完畢。
5. 佈局調優工具
- 背景
儘管已經注意到上述的優化策略,但實際開發中難免還是會出現佈局效能的問題 - 解決方案
使用 佈局調優工具
此處主要介紹 常用的:
hierarchy viewer
、Profile GPU Rendering
、Systrace
5.1 Hierarchy Viewer
簡介
Android Studio
提供的UI效能檢測工具。- 作用
視覺化獲得UI佈局設計結構 & 各種屬性資訊,幫助我們優化佈局設計
即 :方便檢視
Activity
佈局,各個View
的屬性、佈局測量-佈局-繪製的時間- 作用
5.2 Profile GPU Rendering
簡介
一個 圖形監測工具作用
渲染、繪製效能追蹤能實時反應當前繪製的耗時
具體使用
橫軸 = 時間、縱軸 = 每幀的耗時;隨著時間推移,從左到右的重新整理呈現提供一個標準的耗時,如果高於標準耗時,就表示當前這一幀丟失
5.3 Systrace
- 簡介
Android 4.1
以上版本提供的效能資料取樣 & 分析工具 作用
檢測Android
系統各個元件隨著時間的執行狀態 & 提供解決方案- 收集 等執行資訊,從而幫助開發者更直觀地分析系統瓶頸,改進效能
檢測範圍包括:Android
關鍵子系統(如WindowManagerService
等Framework
部分關鍵模組)、服務、View系統 - 功能包括:跟蹤系統的
I/O
操作、核心工作佇列、CPU
負載等,在 UI 顯示效能分析上提供很好的資料,特別是在動畫播放不流暢、渲染卡等問題上
- 收集 等執行資訊,從而幫助開發者更直觀地分析系統瓶頸,改進效能
6. 總結
- 本文主要講解
Android
效能優化中的 繪製優化
- 下面我將繼續深入講解
Android
中的效能優化 ,有興趣可以繼續關注Carson_Ho的安卓開發筆記