性能優化之過度繪製篇

最近接到一個任務,優化項目中的過度繪製問題。提到過度繪製,腦海中會浮現出includemergeViewStub標籤,減少ViewTree的層次等等優化佈局相關,但具體怎麼進行優化,有一種無從下手的感覺。認真仔細閱讀了官方文檔中關於繪製過度的講解,豁然開朗。
網上關於過度繪製的博客也不少,但自己喜歡對自己做的功能進行總結記錄,所以抽時間寫下本篇博客,對過度繪製進行總結,方便日後查閱。

分析工具

一.使用調試GPU overdraw工具從視覺分析:
手機:設置->輔助功能->開發者選項->調試GPU過度繪製->顯示過度繪製區域
這裏寫圖片描述
二.使用佈局檢查器從ViewTree結構分析:
使用Hierarchy Viewer進行ViewTree結構分析,但打開SDK->tools發現SDK中去掉了hierarchyviewer.bat,新增了Layout Inspector進行替代。
使用方法:Android Studio點擊 Tools > Android > Layout Inspector
使用Layout Inspector選擇對應進程,對相應界面就行佈局檢查,會保存爲.li文件並打開,借用官網的圖進行說明:
共分爲三部分:
View Tree:視圖在佈局中的層次結構。
Screenshot:帶每個視圖可視邊界的設備屏幕截圖。
Properties Table:選定視圖的佈局屬性。
這裏寫圖片描述

優化

優化過度繪製是Android性能優化的重要部分,可從以下幾方面進行優化:
一.去除無用背景:
當佈局中有多重背景時會導致視圖的過度繪製,通過刪除刪除佈局中不需要的背景來減少視圖的過度繪製。
在佈局中,如果存在多個線性佈局重疊時,可以考慮只針對最上層的佈局設置背景色,而不需要每一個佈局(例如LinearLayout)都設置背景色,過多的相同的背景色會導致過度繪製。
二.優化視圖層次結構,減少視圖層級:
優化視圖結構,減少佈局層級,可以有效的較少過度繪製,可使用Lint檢查結果進行參考幫助優化性能。
Lint使用:Android Studio的Analyze> Inspect Code使用Lint工具,查看結果中的performance根據提示進行優化。
1.去除不需要的佈局層級:
可根據上述分析工具Layout Inspector直觀地分析視圖層次結構,減少不需要的視圖層級的繪製。
當然Lint檢測結果中也會有提示,Useless parent layout
比如:
Lint中的提示
(1)This ‘RelativeLayout’ layout or its ‘RelativeLayout’ parent is useless; transfer the ‘background’ attribute to the other view。
但只會檢測出最外層佈局且檢查不全面,具體需要根據Layout Inspector分析佈局層次,一層佈局通過添加背景,marginLeft等屬性就可實現的效果沒必要多層嵌套。
(2)Layout hierarchy is too deep
(3)Layout has too many views
對應佈局中有太深層級和太多view的警告,有時功能界面確實複雜,但我們贏儘可能地減少view的使用和佈局層次,必要時使用include,merge,viewStub進行優化。
2.TextView儘量使用CompoundDrawable::
佈局中圖標和文字的結合,這樣的效果太普通不過了,可能會習慣使用LinearLayout/ReleativeLayout下嵌套ImageView和TextView來實現佈局效果。
在LinearLayout佈局中,如果存在相鄰的ImageView和TextView,可以使用compound drawable合二爲一成爲一個TextView,ImageView中的圖片變成TextVIew的drawableTop/drawableLeft/drawableRight/ddrawableBottom屬性,之間的間隔使用drawablePadding屬性來代替。
比如:
Lint中的提示:
Node can be replaced by a TextView with compound drawables
但有些效果使用textview的drawable屬性並不能實現相同的效果,此時還是需要使用多個view來實現的。
3.優化嵌套layout weights:
Lint 中的提示:
Nested layout weights
嵌套layout weights時權值會被計算兩次, 改變時, 會按照比例進行改變,影響性能。此時應使用RelativeLayout或GridLayout代替LinearLayout減少沒必要的layout weights嵌套。
4.使用include,merge,viewStub標籤:
(1).include標籤共享佈局:
將通用的佈局抽取出來,獨立成一個XML文件,在需要用到的頁面中使用include標籤引入進來,減少代碼量,便於修改。
(2).ViewStub標籤實現延遲加載:
ViewStub是一種不可視並且大小爲0的視圖,可以延遲到運行時才填充佈局資源。當ViewStub設置爲可見或者被inflate之後,會填充佈局資源,ViewStub會被填充的視圖代替,和普通的視圖沒有區別。
ViewStub在需要顯示的時候纔會進行視圖的填充,實現延遲加載的目的。
(3).merge標籤減少佈局層次:
當一個獨立的佈局文件最外層是FrameLayout且這個佈局不需要設置背景等屬性時或者當前佈局是另外一個佈局的子佈局時,可以使用merge來減少佈局的層次。
5.在自定義view的onDraw()中過度繪製問題。
在自定義view的onDraw中,如果涉及到重疊的繪製view時,可以考慮利用局部繪製避免過度繪製。
考慮到效率和性能問題,界面是有一定刷新頻率的,每一次刷新都會調用View的onDraw方法,而View提前繪製就是在onDraw中進行,避免在onDraw創建對象,避免在onDraw進行繪製,應在構造函數中畫好,交給onDraw。

總結

在網上查的資料都是理論篇,具體的需要在實踐中理解Android的繪製原理,優化過度繪製,從而給用戶更流暢的畫面和更好的體驗。
參考文章
https://developer.android.com/topic/performance/rendering/overdraw
https://blog.csdn.net/qq_19711823/article/details/65627790