Android效能優化:手把手帶你全面瞭解 繪製優化
前言
- 在
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 過度繪製的優化原則
很多 過度繪製是難以避免的,如 上述例項的 文字 & 背景導致的過度繪製;只能儘可能避免過度繪製:
- 儘可能地控制 過度繪製的次數 = 2 次(綠色)以下,藍色最理想
- 儘可能避免 過度繪製的粉色 & 紅色情況
- 不允許 3 次以上的過度繪製(淡紅色)面積 超過 螢幕大小的 1/4
4.2.4 優化方案
1.移除預設的 Window 背景
2.移除 控制元件中不必要的背景
3.減少佈局檔案的層級(巢狀)
4.自定義控制元件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 則無必要設定,可移除

示意圖
優化方案3:減少佈局檔案的層級(減少不必要的巢狀)
- 原理:減少不必要的巢狀 ->> UI層級少 ->> 過度繪製的可能性低
- 優化方式:使用佈局標籤<merge> & 合適選擇佈局型別
優化方案4:自定義控制元件View優化:使用 clipRect() 、 quickReject()
-
clipRect()
1.作用:給 Canvas 設定一個裁剪區域,只有在該區域內才會被繪製,區域之外的都不繪製
2 例項說明: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系統各個元件隨著時間的執行狀態 & 提供解決方案
1.收集 等執行資訊,從而幫助開發者更直觀地分析系統瓶頸,改進效能檢測範圍包括:Android 關鍵子系統(如WindowManagerService 等 Framework 部分關鍵模組)、服務、View系統 2.功能包括:跟蹤系統的I/O 操作、核心工作佇列、CPU 負載等,在 UI 顯示效能分析上提供很好的資料,特別是在動畫播放不流暢、渲染卡等問題上
-
具體使用
Systrace 使用指南
6. 總結
- 本文主要講解Android 效能優化中的 繪製優化

最後給大家分享一份非常系統和全面的Android進階技術大綱及進階資料,及面試題集
想學習更多Android知識,請加入Android技術開發交流 7520 16839
進群與大牛們一起討論,還可獲取Android高階架構資料、原始碼、筆記、視訊
包括 高階UI、Gradle、RxJava、小程式、Hybrid、移動架構、React Native、效能優化等全面的Android高階實踐技術講解效能優化架構思維導圖,和BATJ面試題及答案!
群裡免費分享給有需要的朋友,希望能夠幫助一些在這個行業發展迷茫的,或者想系統深入提升以及困於瓶頸的朋友,在網上部落格論壇等地方少花些時間找資料,把有限的時間,真正花在學習上,所以我在這免費分享一些架構資料及給大家。希望在這些資料中都有你需要的內容。
Android高階技術大綱,以及系統進階視訊,及面試題和答案

面試題及答案

Android高階技術大綱

Android 進階視訊資料