導言
這節(jié)主要講的是UI優(yōu)化方面關于GPU相關的知識,比方說過渡繪制和硬件加速
過渡繪制
在Google的教程中我們可以看到人家專門提了過渡繪制的問題,這個在平時使用的時候也非常的簡單,直接找到手機的開發(fā)者選項媚创,然后打開GPU過渡繪制即可
這里可以看到一些控件上面有一些顏色,這些顏色就是用于反饋過渡繪制的程度
1.白色:沒有過渡繪制
2.藍色:過渡繪制一次
3.淺綠色:過渡繪制兩次
4.淺紅色:過渡繪制三次
5.紅色:過渡繪制四次及以上
過渡繪制所導致問題就是在繪圖的時候可能會重復繪制一些用戶并不能看到的像素點,比方說一些互相重疊的視圖荤西,從而造成性能方面的損失
常用的解決方案
<style name="easy_overdraw" parent="AppTheme">
<item name="android:windowBackground">@null</item>
</style>
因為視圖默認是展示在window上面,而window本身就有一個背景,在很多時候邪锌,你不能確定窗體的背景是否有展示的必要勉躺,而且完全可以用更高層級的視圖背景來替代,從而降低過渡繪制
此外就是注意自身的布局觅丰,減少不必要的重疊以及背景饵溅,一般原則上就是層級越低的布局優(yōu)先設置背景,否則才考慮頂層布局設置背景妇萄。
減少重疊有一個方案蜕企,這個可以參考官方的DrawerLayout中的代碼
if (drawingContent) {
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View v = getChildAt(i);
if (v == child || v.getVisibility() != VISIBLE
|| !hasOpaqueBackground(v) || !isDrawerView(v)
|| v.getHeight() < height) {
continue;
}
if (checkDrawerViewAbsoluteGravity(v, Gravity.LEFT)) {
final int vright = v.getRight();
//只選擇了抽屜右邊的區(qū)域
if (vright > clipLeft) clipLeft = vright;
} else {
final int vleft = v.getLeft();
//只選擇了抽屜左邊的區(qū)域
if (vleft < clipRight) clipRight = vleft;
}
}
canvas.clipRect(clipLeft, 0, clipRight, getHeight());
}
重點關注clipRect方法
/**
* Intersect the current clip with the specified rectangle, which is
* expressed in local coordinates.
*
* @param left The left side of the rectangle to intersect with the
* current clip
* @param top The top of the rectangle to intersect with the current clip
* @param right The right side of the rectangle to intersect with the
* current clip
* @param bottom The bottom of the rectangle to intersect with the current
* clip
* @return true if the resulting clip is non-empty
*/
public boolean clipRect(int left, int top, int right, int bottom) {
return nClipRect(mNativeCanvasWrapper, left, top, right, bottom,
Region.Op.INTERSECT.nativeInt);
}
從注釋中可以看出,實際上就是指定繪制的區(qū)域冠句,也就是說可以通過該方法來優(yōu)化繪制的范圍轻掩。
DrawerLayout就是通過這個方法,來避免當抽屜出現(xiàn)的時候重復繪制內(nèi)容被遮擋的部分懦底,從而優(yōu)化過渡繪制
硬件加速
平炒侥粒看視頻之類的都知道有一個硬件加速,在Android中同樣也可以使用基茵,通過View的
setLayerType(LAYER_TYPE_HARDWARE,null);
可以指定開啟硬件加速層奋构,看一下具體的注釋
/**
* <p>Indicates that the view has a hardware layer. A hardware layer is backed
* by a hardware specific texture (generally Frame Buffer Objects or FBO on
* OpenGL hardware) and causes the view to be rendered using Android's hardware
* rendering pipeline, but only if hardware acceleration is turned on for the
* view hierarchy. When hardware acceleration is turned off, hardware layers
* behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
*
* <p>A hardware layer is useful to apply a specific color filter and/or
* blending mode and/or translucency to a view and all its children.</p>
* <p>A hardware layer can be used to cache a complex view tree into a
* texture and reduce the complexity of drawing operations. For instance,
* when animating a complex view tree with a translation, a hardware layer can
* be used to render the view tree only once.</p>
* <p>A hardware layer can also be used to increase the rendering quality when
* rotation transformations are applied on a view. It can also be used to
* prevent potential clipping issues when applying 3D transforms on a view.</p>
*
* @see #getLayerType()
* @see #setLayerType(int, android.graphics.Paint)
* @see #LAYER_TYPE_NONE
* @see #LAYER_TYPE_SOFTWARE
*/
public static final int LAYER_TYPE_HARDWARE = 2;
注釋中提到,開啟硬件加速層可以很有效的進行視圖樹繪制緩存拱层,降低繪制的次數(shù)弥臼,這樣對于一些復雜的動畫來說是一個非常大的優(yōu)化,也就是說在使用動畫的時候應該考慮開啟硬件加速進行優(yōu)化
但是注意硬件加速會帶來其他的問題根灯,比方說在GPU層會有明顯的內(nèi)存占用增加
可以看到GPU層所使用的內(nèi)存大量增加径缅,所以一般來說在動畫結束之后需要關閉硬件加速層,從而去釋放這一部分的內(nèi)存烙肺,比方說
text1.setLayerType(View.LAYER_TYPE_HARDWARE,null)
val animator = ValueAnimator.ofFloat(0.0f,90.0f)
animator.addUpdateListener {
text1.rotation = it.animatedValue as Float
}
animator.addListener(object :Animator.AnimatorListener{
override fun onAnimationRepeat(animation: Animator?) {
}
override fun onAnimationCancel(animation: Animator?) {
text1.setLayerType(View.LAYER_TYPE_NONE,null)
}
override fun onAnimationStart(animation: Animator?) {
}
override fun onAnimationEnd(animation: Animator?) {
text1.setLayerType(View.LAYER_TYPE_NONE,null)
}
})
animator.setTarget(text1)
animator.repeatCount = ValueAnimator.INFINITE
animator.start()
總結
這部分主要是介紹了過渡繪制的處理以及硬件加速的使用纳猪,是關于GPU層的一種優(yōu)化手段
文章系列:
基本的優(yōu)化總結(一)
基本的優(yōu)化總結(二)
基本的優(yōu)化總結(三)
基本的優(yōu)化總結(四)
基本的優(yōu)化總結(五)
基本的優(yōu)化總結(六)
基本的優(yōu)化總結(七)