什麼是overdraw?
overdraw就是螢幕上某個畫素點在同一幀被繪製了多次。在多層布局結構中,不可見部分也會被繪製。舉個例子,乙個白色頁面上有乙個按鈕。系統首先繪製白色背景,然後在白色背景上繪製按鈕,最後在按鈕背景上繪製按鈕內容。那麼按鈕和按鈕內容就造成了overdraw。
其實overdraw是不可避免的,我們要做的是檢查overdraw次數過多的地方,並刪掉無用的繪製。
如何檢查overdraw?
在開發者工具中勾選show gpu overdraw選項,觀察ui上的overdraw情況。
該工具會以不同的顏色繪製在螢幕上,標識出該塊ui的overdraw情況。
如果是透明色,表示只繪製了一次,沒有overdraw。
我們要做的就是減少大面積的紅色區域,使其變成藍色甚至是透明色。對於深紅色,就要思考出了什麼問題,堅決進行優化。
優化菜鳥裹裹物流詳情頁面
首先開啟show gpu overdraw選項,觀察一下情況。
相當恐怖,幾乎全是深紅色。
分析overdraw原因
布局結構:基於listview展示,快遞資訊、物品資訊、小件員資訊在同乙個view封裝,作為headerview加入listview,listview的item展示物流跟蹤資訊。
繪製層級:
第一層:window背景
第二層:activity中fragment container背景
第三層:fragment中listview背景
第四層:listview的header背景和物流資訊item背景
第五層:快遞資訊、物品資訊、小件員資訊背景和物流資訊item內容
第六層+:快遞資訊、物品資訊、小件員資訊內容
開始優化
第一步,刪除window預設背景
android系統提供了預設的背景,被decorview持有,但是通常情況,我們會為全屏提供自定義顏色,那麼這個背景就沒用了,反而會帶來一次overdraw的效能損耗。
activity的oncreate方法中,呼叫getwindow().setbackgrounddrawable(null)即可刪除這個預設背景。
注意,這個方法應該在setcontentview後呼叫。原因通過分析原始碼可知:
setcontentview通過呼叫phonewindow的setcontentview,再到installdecor。最終通過以下**設定背景:
if (mdecor.getbackground() == null &&mbackgroundfallbackresource != 0)
而getwindow().setbackgrounddrawable(null)同樣會呼叫phonewindow的以下方法:
public
final
void
setbackgrounddrawable(drawable drawable)
if (mbackgroundfallbackresource != 0) }}
可以看出,如果先呼叫getwindow().setbackgrounddrawable(null), setcontentview會再次設定背景色。
因此,getwindow().setbackgrounddrawable(null)應該在setcontentview之後呼叫。
第二步,刪除布局中重複設定的背景
整個布局基於listview全屏展示,因此和activity中fragment container背景衝突,保留其中之一即可,在這裡選擇刪除listview的背景,由container設定整體背景。
優化效果初見成效,滿屏的紅色沒有了,取而代之的是大塊的綠色和藍色,小塊淡紅色和極少的深紅色。
第三步,優化headerview
從ui設計來看,headerview的幾個區塊是白色背景,中間用灰色分割。
原來的實現方案是root view設定灰色背景,sub view使用margin暴露root view底色。如下圖:
這裡是存在優化空間的,可以將雙層結構改為單層,區塊之間的分割使用灰色背景的view即可。修改後的結構如下圖:
通過布局結構的優化,可以使headerview再減少一次overdraw。
第四步,細粒度優化
觀察第二步優化後的情況,可以發現,物品資訊textview和快遞圖示imageview還是存在深紅色。
檢查布局檔案發現,textview設定了和parent view相同的背景色,這很簡單,刪除即可。
快遞圖示使用了兩個imageview組成,乙個展示快遞圖示,另乙個為圖示增加了邊框。我將兩個imageview進行合併,通過src屬性展示圖示,background屬性設定邊框,並增加了1px的padding把邊框展示出來。
而物品圖示使用了自定義的imageview,使用上述優化手段存在bug,暫不做處理。
至此,優化工作完成,下圖是優化後的效果。
可以看出,整屏基本上都是藍色,少量綠色以及小面積的淡紅色,基本達到了優化效果。
最後,總結一下優化步驟
刪除window預設背景。
刪除多層布局結構中重複設定的背景
優化布局,減少布局層次。
檢查元件,刪繁去冗。
Android UI效能優化(渲染)
谷歌05年初發布效能優化典範,是的開發者學會如何去識別 診斷 解決安卓應用開發中所存在的效能問題。首當其衝的便是渲染的效能優化。在正常的開發中,可以移除不必要的background,以減少繪製的程度。如設定了主布局檔案的背景顏色,就可以移除listview以及listview的items中的一些ba...
Android UI效能優化 理論篇
如果你的某個操作花費時間是24ms,系統在得到vsync訊號的時候就無法進行正常渲染,這樣就發生了丟幀現象。那麼使用者在32ms內看到的會是同一幀畫面。使用者容易在 ui 執行動畫或者滑動 listview 的時候感知到卡頓不流暢,是因為這裡的操作相對複雜,容易發生丟幀的現象,從而感覺卡頓。有很多原...
Android UI效能優化 過度繪製篇
每過幾年,就會有傳聞說某個博物館在用x光掃瞄一副無價的名畫之後,發現畫作的作者其實重用了老的畫布,在名畫的底下還藏著另一副沒有被發現的畫作。有時候,博物館還能用高階的影象技術來還原畫布上的原作。android裡面的view的繪製就是類似的情況。當android系統繪製螢幕的時候,先畫父view,然後...