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

 

 

 

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