Android UI效能優化 Overdraw

2021-08-02 13:52:59 字數 3156 閱讀 9438

什麼是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,然後...