Android 效能最佳化——之控制項的最佳化,android效能最佳化
Android 效能最佳化——之控制項的最佳化
前面講了映像的最佳化,接下來分享一下控制項的效能最佳化,這裡主要是面向自訂View的最佳化。
1、首先先說一下我們在自訂View中可能會犯的3個錯誤:
1)Useless calls to onDraw():我們知道調用View.invalidate()會觸發View的重繪,有兩個原則需要遵守,第1個是僅僅在View的內容發生改變的時候才去觸發invalidate方法, 第2個是盡量使用ClipRect等方法來提高繪製的效能。
2)Useless pixels:減少繪製時不必要的繪製元素,對於那些不可見的元素,我們需要盡量避免重繪。
3)Wasted CPU cycles:對於不在螢幕上的元素,可以使用Canvas.quickReject把他們給剔除,避免浪費CPU資源。另外盡量使用GPU來進行UI的渲染,這樣能夠極大的提高程 序的整體表現效能。
下面我介紹一下關於最佳化的東西
1、避免在onDraw()方法中執行導致記憶體配置的操作,例如new Paint()。
首先onDraw()方法是執行在UI線程的,在UI線程盡量避免做任何可能影響到效能的操作。雖然分配記憶體的操作並不需要花費太多系統資源,但是 這並不意味著是免費無代價 的。裝置有一定的重新整理頻率,導致View的onDraw方法會被頻繁的調用,如果onDraw方法效率低下,在頻繁重新整理累積的效 應下,效率低的問題會被擴大,然後會對效能有嚴重 的影響。
只有view內容改變的時候,調用invalidate()方法更新介面。
對於不在螢幕上的元素,可以調用Canvas.quickReject()方法剔除,避免資源浪費。
例如當你滑動介面的時候,系統就會頻繁的調用onDraw()方法,這是就會在短時間內佔有大量的記憶體。會出現記憶體抖動,GC會頻頻的觸發,會影響到CPU的效率,並且會造成 手機電量的大量消耗。
2、減少alpha值對效能的影響。
在很多的自訂View中,為了讓介面更加美觀,設定了alpha值,來讓View變成透明狀態的,顯得高大上一些,但是這對效能卻是一定的負擔。通常來說,對於不透明的View,顯示它只需要渲染一次即可,可是如果這個View設定了alpha 值,會至少需要渲染兩次。原因是包含alpha的view需要事Crowdsourced Security Testing道混合View的下一層元素是什麼,然後再結合上層的View進行Blend混色處 理。
在某些情況下,一個包含alpha的View有可能會觸發改View在HierarchyView上的父View都被額外重繪一次。下面我們看一個例子,示範的ListView中的圖片與二級標題都有設定透明度。
大多數情況下,螢幕上的元素都是由後向前進行渲染的。在上面的圖示中,會先渲染背景圖(藍,綠,紅),然後渲染人物頭像圖。如果後渲染的元素有設定 alpha值,那麼這個元素就會和螢幕上已經渲染好的元素做blend處理。很多時候,我們會給整個View設定alpha的來達到fading的動畫效 果,如果我們圖示中的ListView做alpha逐漸減小的處理,我們可以看到ListView上的TextView等等組件會逐漸融合到背景色上。但 是在這個過程中,我們無法觀察到它其實已經觸發了額外的繪製任務,我們的目標是讓整個View逐漸透明,可是期間ListView在不停的做 Blending的操作,這樣會導致不少效能問題。
如何渲染才能夠得到我們想要的效果呢?我們可以先按照通常的方式把View上的元素按照從後到前的方式繪製出來,但是不直接顯示到螢幕上,而是使用 GPU預先處理之後,再又GPU渲染到螢幕上,GPU可以對介面上的未經處理資料直接做旋轉,設定透明度等等操作。使用GPU進行渲染,雖然第一次操作相比起直 接繪製到螢幕上更加耗時,可是一旦原始紋理資料產生之後,接下去的操作就比較省時省力。
如何才能夠讓GPU來渲染某個View呢?我們可以通過setLayerType的方法來指定View應該如何進行渲染,從SDK 16開始,我們還可以使用ViewPropertyAnimator.alpha().withLayer()來指定。如所示:
另外一個例子是包含陰影地區的View,這種類型的View並不會出現我們前面提到的問題,因為他們並不存在層疊的關係。
為了能夠讓渲染器知道這種情況,避免為這種View佔用額外的GPU記憶體空間,我們可以做下面的設定。
通過上面的設定以後,效能可以得到顯著的提升,如所示: