標籤:IV dep 感知 form moni measure androi 項目 視窗
前言
原來My Code寫得這麼爛!
為什麼最佳化
卡頓現象,由於複雜的布局或介面過度繪製未能在每幀16ms內完成導致的。
複雜的布局
Android系統每隔16ms發出VSYNC訊號,觸發對UI進行渲染,要每次渲染都成功,這樣就必須達到流暢的畫面所需要的60fps,否則會發生丟幀的現象,丟幀越多,使用者明確感到卡頓。
補充:
1、fps,每秒顯示幀數,幀率測量單位(frames per second);
2、為什麼是60fps(16ms=1000/60)?因為人眼與大腦之間的協作無法感知超過60fps的畫面更新。
過度繪製
Overdraw(過度繪製)是指系統在單個渲染幀中多次繪製螢幕上的像素。例如,如果我們有一堆堆疊的UI卡,不可見的UI也在做繪製的操作,這樣會浪費大量的CPU和GPU資源。
補充:
渲染操作通常依賴於兩個核心組件:CPU與GPU。CPU負責包括Measure,Layout,Record,Execute的計算操作,GPU負責Rasterization(柵格化)操作。
如何檢測
Show GPU Overdraw
開啟Show GPU Overdraw選項進行觀察是否存在過度繪製。
步驟:
設定 -> 開發人員選項 -> 調試GPU過度繪製 ->顯示過度繪製地區。
對比一張Overdraw的參考圖,分別有藍色,淡綠,淡紅,深紅代表了4種不同程度的Overdraw情況:
藍色: 意味著overdraw 1倍,像素繪製了兩次;
綠色: 意味著overdraw 2倍,像素繪製了三次;
淡紅: 意味著overdraw 3倍,像素繪製了四次;
深紅: 意味著overdraw 4倍,像素繪製了五次或者更多。
我們的目標就是盡量減少紅色Overdraw,看到更多的藍色地區。
Profile GPU Rendering
開啟Profile GPU Rendering,顯示每幀畫面所需要渲染的時間。
步驟:
設定 -> 開發人員選項 -> GPU呈現模式分析 -> 在螢幕上顯示為橫條圖
介面上會滾動顯示垂直的柱狀圖來表示每幀畫面所需要渲染的時間,柱狀圖越高表示花費的渲染時間越長。中間有一根綠色的橫線,代表16ms,我們需要確保每一幀花費的總時間都低於這條橫線,這樣才能夠避免出現卡頓的問題。
Hierarchy Viewer
用Hierarchy Viewer工具檢查Activity中的布局是否過於複雜
步驟:
Tools -> Android -> Android Device Monitor。
開啟Hierarchy Viewe:
啟動Android Device Monitor成功之後,在新的的視窗中點擊切換視圖表徵圖,選擇Hierarchy Viewe:
使用Hierarchy Viewer:
其實中帶有紅色或×××的點代錶速度較慢的View。
友情提示:
APP先運行起來再使用Android Device Monitor,建議用模擬器,手機可能讀不到內容。
TraceView
使用TraceView來觀察CPU執行情況,使用詳見:效能分析工具 Android TraceView。
最佳化
刪除不必要的布局背景
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="?attr/backgroundColor" android:orientation="vertical"> <com.wuxiaolong.pullloadmorerecyclerview.PullLoadMoreRecyclerView android:id="@+id/pullLoadMoreRecyclerView" android:layout_width="match_parent" android:layout_height="match_parent"/></LinearLayout>
如果這裡PullLoadMoreRecyclerView也設定背景色是沒有必要了。
另外,使用Android一些內建的主題,window被預設添加一個純色的背景,theme中添加android:windowbackground=”null”除掉或添加自己需要的背景色,減少渲染。
最佳化布局層次
通過最佳化視圖階層,以減少重疊的UI對象的數量來提高效能。
這裡得糾正我一個錯誤,我平時不想使用RelateLayout,是因為不想每個都命名id,命名是件很頭疼的事,所以我更多使用了LinearLayout布局。為了提高效能,還是盡量多使用RelativeLayout吧。
使用include、merge、ViewStub
1、include布局重用;
2、merge減少視圖層級;
3、ViewStub標籤是當你需要時才會載入
詳細介紹見:Android抽象布局——include、merge 、ViewStub
自訂群組件的onDraw()
1、避免大量建立臨時對象,比如String,以免頻繁觸發GC;
2、考慮使用canvas.clipRect()繪製需要被繪製的地區。
ListView
1、考慮使用ViewHolder;
2、或者RecycleView來代替
Lint
Lint是一個代碼掃描工具,能夠協助我們識別代碼結構存在的問題。在布局檔案上運行lint工具來搜尋可能的視圖階層最佳化是一種很好的做法。
步驟:Android Studio,Analyze -> Inspect Code。
布局資訊將顯示在Android> Lint> Performance下:
要查看更多詳細資料,您可以單擊每個項目來展開它,並在螢幕右側的窗格中查看更多資訊。
lint規則:
Use compound drawables - A LinearLayout which contains an ImageView and a TextView can be more efficiently handled as a compound drawable.
Merge root frame - If a FrameLayout is the root of a layout and does not provide background or padding etc, it can be replaced with a merge tag which is slightly more efficient.
Useless leaf - A layout that has no children or no background can often be removed (since it is invisible) for a flatter and more efficient layout hierarchy.
Useless parent - A layout with children that has no siblings, is not a ScrollView or a root layout, and does not have a background, can be removed and have its children moved directly into the parent for a flatter and more efficient layout hierarchy.
Deep layouts - Layouts with too much nesting are bad for performance. Consider using flatter layouts such as RelativeLayout or GridLayout to improve performance. The default maximum depth is 10.
Lint除了layout最佳化,還能檢查編碼、可訪問性等問題。
Android 渲染最佳化