UI流暢度

1.流暢度定義

16.67ms刷新一幀即一個Vsync

2.界面機制

code或xml編寫界面佈局,轉成DisplayList,由屏幕展示

3.案例分析

as GPU Render:分析是否掉幀

Overdraw 像素點多次繪製,綠色是1次,藍色是2次,紅色是3次以上

systrace性能分析,耗時分析

traceview 具體分析每個線程,每個函數耗時

4.總結

overdraw:

原因:1.繪製未展示的UI;2.重複繪製相同ui或已存在的ui;

優化:

1.可以通過canvas.clipRect()來幫助系統識別那些可見的區域。這個方法可以指定一塊矩形區域,只有在這個區域內纔會被繪製,其他的區域會被忽視,即局部繪製的思想;clipRect方法還可以幫助節約CPU與GPU資源,在clipRect區域之外的繪製指令都不會被執行,那些部分內容在矩形區域內的組件,仍然會得到繪製。

2.使用canvas.quickreject()來判斷是否沒和某個矩形相交。若判斷與矩形相交,則可跳過相交的區域,從而減少過度繪製。

3.移除不需要的backgrand(默認windows的背景色):可以在代碼中getWndow.setBackgrandDrawable(null) 或xml中設置爲null如style中

 <item name="android:windowBackground">@null</item>

4.透明度渲染

setLayerType設置硬件加速,可以加速渲染

使用View layers(硬件層),我們可以將view渲染入一個非屏幕區域緩衝區(off-screen buffer,前面透明度部分提到過),並且根據我們的需求來操控它。這個功能主要是針對動畫,因爲它能讓複雜的動畫效果更加的流暢。而不使用硬件層的話,View會在動畫屬性(例如coordinate, scale, alpha值等)改變之後進行一次刷新。而對於相對複雜的view,這一次刷新又會連帶它所有的子view進行刷新,並各自重新繪製,相當的耗費性能。使用View layers,通過調用硬件層,GPU直接爲我們的view創建一個結構,並且不會造成view的刷新。而我們可以在避免刷新的情況下對這個結構進行進行很多種的操作,例如x/y位置變換,旋轉,透明度等等。總之,這意味着我們可以對一個讓一個複雜view執行動畫的同時,又不會刷新!這會讓動畫看起來更加的流暢

// Using the Object animator
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, 20f);
objectAnimator.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        view.setLayerType(View.LAYER_TYPE_NONE, null);
    }
});
objectAnimator.start();
 
// Using the Property animator
view.animate().translationX(20f).withLayer().start();

有幾點要牢記在心:

 

  • 回收 – 硬件層會佔用GPU中的一塊內存。只在必要的時候使用他們,比如動畫,並且事後注意回收。例如在上面ObjectAnimator的例子中,我們增加了一個動畫結束監聽以便在動畫結束後可以移除硬件層。而在Property animator的例子中,我們使用了withLayers(),這會在動畫開始時候自動創建硬件層並且在結束的時候自動移除。
  • 如果你在調用了硬件View layers後改變了View,那麼會造成硬件硬件層的刷新並且再次重頭渲染一遍view到非屏幕區域緩存中。這種情況通常發生在我們使用了硬件層暫時還不支持的屬性(目前爲止,硬件層只針對以下幾種屬性做了優化:otation、scale、x/y、translation、pivot和alpha)。例如,如果你另一個view執行動畫,並且使用硬件層,在屏幕滑動他們的同時改變他的背景顏色,這就會造成硬件層的持續刷新。而以硬件層的持續刷新所造成的性能消耗來說,可能讓它在這裏的使用變得並不那麼值。

5.繪製陰影的時候,在hasOverlappingRender回調中返回false。

在android的View裏有透明度的屬性,當設置透明度setAlpha的時候,android裏默認會把當前view繪製到offscreen buffer中,然後再顯示出來。 這個offscreen buffer 可以理解爲一個臨時緩衝區,把當前View放進來並做透明度的轉化,然後在顯示到屏幕上。這個過程是消耗資源的,所以應該儘量避免這個過程。

當繼承了hasOverlappingRendering()方法返回false後,android會自動進行合理的優化,避免使用offscreen buffer。

需要注意的是,當調用forceHasOverlappingRendering(boolean b)後這個方法就會被忽略。

6.減少層級減少嵌套,用輕量級的控件實現ui

 

 

 


————————————————
版權聲明:本文爲CSDN博主「星辰旋風」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/xingchenxuanfeng/article/details/56488045

 

https://www.jianshu.com/p/cbdaeb1bede5

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章