文章目錄
一、 GPU 過度繪製優化總結
前兩篇博客回顧 :
【Android 性能優化】佈局渲染優化 ( 過渡繪製 | 自定義控件過渡繪製 | 佈局文件層次深 | GPU 過渡繪製調試工具 | 背景過度繪製 ) 講解的是佈局文背景設置 , 導致的 GPU 渲染過程中過度繪製 , 如何調試 GPU 渲染 , 主題背景與佈局背景設置造成的過度繪製 , 及推薦處理方案 , 刪除主題背景 ;
【Android 性能優化】佈局渲染優化 ( 過渡繪製 | 背景設置產生的過度繪製 | Android 系統的渲染優化 | 自定義佈局渲染優化 ) 博客中講解了佈局文件中的背景如何處理 , 自定義組件在 GPU 渲染過程中過度繪製如何進行處理 ; 還有 Android 系統針對 CPU 傳遞數據到 GPU 進行的優化 ;
耗時操作總結 :
在 【Android 性能優化】佈局渲染優化 ( CPU 與 GPU 架構分析 | 安卓佈局顯示流程 | 視覺與幀率分析 | 渲染超時卡頓分析 | 渲染過程與優化 ) 博客中分析了圖像渲染的 16 毫秒過程中
- CPU 渲染
- CPU 傳遞數據到 GPU
- GPU 渲染
是三大耗時操作 , 之前的兩篇博客針對 GPU 渲染中的過度繪製 , 如何調試 , 如何優化 , 進行了簡要介紹 ; CPU 傳遞數據到 GPU 過程是 Android 自己優化的 , 不需要開發者干預 ;
本篇博客開始針對 CPU 渲染過程進行詳細講解 , CPU 渲染優化 , 主要是提升 CPU 渲染的速度 , 即減少佈局的嵌套 ;
上述優化過程中 , 需求是第一位的 , 不能爲了優化而優化 , 假如需求就是這種要求 , 那隻能盡最大可能進行 GPU 渲染優化 , 不要盲目追求 區域過度繪製 ;
二、 CPU 渲染過程
CPU 渲染過程 , 就是將 UI 組件轉換成多維向量圖像 ( 多邊形或紋理數據 ) ;
CPU 渲染過程細節 : UI 組件 -> 紋理 流程 , 根據該組件的位置 , 大小 , 形狀 , 顏色 等生成紋理數據 ;
① 加載內存 : 將 UI 組件加載到內存中 ;
② 調用 UI 組件的 invalidate 方法 ;
③ 測量 : 調用 onMeasure 方法 , 測量佈局組件 ;
④ 擺放 : 調用 onLayout 方法 , 擺放組件 ;
⑤ 圖像轉換 : 將測量擺放好的圖像 , 展示出來 , 轉爲多維向量圖像 , 傳遞給 GPU ;
三、 CPU 渲染性能調試工具 Layout Inspector
在之前調試 GPU 渲染新能時 , 使用了手機開發者模式下的 “調試 GPU 過度繪製” 工具 , CPU 渲染使用下面介紹的 “Layout Inspector” 工具 ;
老版本的 Android Studio 中還可以使用 Hierarchy Viewer 工具 , 新版本的 Android Studio 已不支持該工具 , 使用 Layout Inspector 替代 ;
CPU 渲染性能調試工具 :
① 工具選擇 : 優化 CPU 渲染情況 , 需要先知道 CPU 渲染的當前性能 , 原來使用的是 Hierarchy Viewer 工具 ( 目前已不支持 ) , 現在使用 Layout Inspector 工具 ;
② 打開 Layout Inspector 工具 : 在 Android Studio 中 , 點擊菜單欄 “Tool” , 選擇 “Layout Inspector” 工具 , 即可打開該工具 ;
③ 選擇進程 : 在彈出的 “Choose Process” 對話框中 , 選擇要分析的 UI 佈局所在的進程 ;
④ Layout Inspector 工具截圖 :
⑤ 左側 View Tree 組件樹視圖 : 這是組件樹視圖 , 該視圖中可以清晰看到佈局的層級 ;
四、 Layout Inspector 組件樹 DecorView 分析
手機界面窗口 : DecorView 是手機界面佈局中的根佈局 , 代表了手機屏幕窗口 ;
① 界面內容 : LinearLayout 代表了顯示的內容 ;
② 導航欄 : id/navigationBarBackground 代表了底部的 回退鍵 , Home 鍵 , 菜單鍵 按鈕的導航欄佈局 ;
③ 狀態欄 : id/statusBarBackground 代表了狀態欄佈局 ;
五、 實際的界面 UI 佈局組件層級分析
1 . Layout Inspector 中查看實際的 UI 佈局層次 : 圖中藍色被選中的部分是開發者定義的佈局組件 , 其它都是系統自動生成的 ;
2 . UI 佈局代碼 : 該佈局使用了約束佈局 , 只嵌套了 層
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/sample_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- 預覽 Camera 採集的圖像數據 -->
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/textViewUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:text="推流地址 : "
android:padding="5dip"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0"/>
<Button
android:id="@+id/button_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="開始推流"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1"/>
</androidx.constraintlayout.widget.ConstraintLayout>