Android优化之Hardware Layer

项目中越来越多的动画,越来越多的效果导致了应用性能越来越低。该如何提升。

简介

View播放动画的过程中每一帧都需要被重绘。如果使用view layers,就不用每帧都去重绘,因为View渲染一旦离开屏幕缓冲区就可以被重用。

而且,hardware layers会在GPU上缓存,这样就会让一些动画过程中的操作变得更快。通过hardware layers可以快速的渲染一些简单的转变(位移、选中、缩放、颜色渐变)。由于很多动画都是这些动作的结合,所以hardware layers可以显著的提高动画性能。

View当中提供了三种类型的Layer type:

  • LAYER_TYPE_HARDWARE 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 software layers. 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. 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. 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.
  • LAYER_TYPE_SOFTWARE Indicates that the view has a software layer. A software layer is backed by a bitmap and causes the view to be rendered using Android’s software rendering pipeline, even if hardware acceleration is enabled. Software layers have various usages: When the application is not using hardware acceleration, a software layer is useful to apply a specific color filter and/or blending mode and/or translucency to a view and all its children. When the application is using hardware acceleration, a software layer is useful to render drawing primitives not supported by the hardware accelerated pipeline. It can also 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 software layer can be used to render the view tree only once. Software layers should be avoided when the affected view tree updates often. Every update will require to re-render the software layer, which can potentially be slow (particularly when hardware acceleration is turned on since the layer will have to be uploaded into a hardware texture after every update.)
  • LAYER_TYPE_NONE Indicates that the view does not have a layer. 默认值。

使用

首先使用的前提是在清单文件中开启了硬件加速。否则将无法使用hardware layer。这一点在上面的文档中也有说明。

API也是非常简单的,直接使用View.setLayerType()就好。使用时应该只是暂时的设置Hardware Layer,因为它们无法自动释放。 基本的使用步骤:

  • 对每个想要在动画过程中进行缓存的view调用View.setLayerType(View.LAYER_TYPE_HARDWARE, null)方法。
  • 执行动画。
  • 在动画执行结束后调用View.setLayerType(View.LAYER_TYPE_NONE, null)方法来进行清除。

示例:

mView.setLayerType(View.LAYER_TYPE_HARDWARE, null);

animator.addListener(new AnimatorListenerAdapter() {  
  @Override
  public void onAnimationEnd(Animator animation) {
    mView.setLayerType(View.LAYER_TYPE_NONE, null);
  }
});

animator.start();  

但是如果在4.0.x的版本中使用上面的代码会本亏,必须要把setLayerType放到Runnable中。如下:

mView.setLayerType(View.LAYER_TYPE_HARDWARE, null);

animator.addListener(new AnimatorListenerAdapter() {  
  @Override
  public void onAnimationEnd(Animator animation) {
    //This will work successfully
    post(new Runnable() {
        @Override
        public void run () {
            setLayerType(LAYER_TYPE_NONE, null);
        }
    }
  }
});

animator.start();  

如果你基于minSdkVersion 16以上并且使用ViewPropertyAnimator时,你可以使用withLayer()方法替代如上的操作:

mView.animate().translationX(150).withLayer().start();

或者在api 14以上时使用ViewCompat.animate().withLayer() 这样做,你的动画就会变得更流畅!

注意事项

你应该知道,事情没那么简单。 Hardware layers有着惊人的提升动画性能的能力。然而,如果滥用,它的危害更大。不要盲目的使用layers

  • 首先,在有些情况下,hardware layers除了view渲染外还会执行更多的工作。缓存layer将会需要时间,因为首选第一步就需要两个过程: 先将这些view渲染到GPU的一个layer中然后GPU再渲染该layerWindow上。如果要渲染的View非常简单(例如一个纯色值),那么这样在初始化的时候就会增加Hardware Layer不必要的开销。
  • 其次,对所有的缓存来讲,都有一个缓存失效的可能性。任何时候如果在动画过程中调用view.invalidate(),那么layer就必须要重新渲染。经常的废弃hardware layers会比没有layers的情况下更糟糕,因为如同上面讲到的hardware layers在设置缓存时会有额外的开销。如果你需要经常的重新缓存layer,那就会有极大的损害。 这个问题也是非常容易出现的,因为动画经常有多个移动的部分。假如现在有一个三个部分移动的动画: Parent ViewGroup —-> Child View1 (往左移动) —-> Child View2 (往右移动) —-> Child View3 (往上移动) 如果你只在父布局ViewGroup上设置一个layer,那就将经常的缓存失效,因为ViewGroup会随着子View不断地改变。然而对每个单独的子Views而言,他们只是在位移。这种情况下,最好是对每个子View上设置Hardware Layer(而不是在父布局上)。 再次重申,通常是对多个子View上适当的设置Hardware Layer,这样他们就不会在动画运行时失效。 在手机开发者选项中的显示硬件层更新(Show hardware layers updates)功能是追踪这个问题的开发利器。当View渲染Hardware Layer的时候闪烁绿色,它应该在动画开始的时候闪烁一次(也就是Layer渲染初始化的时候),然而,如果你的View在整个动画期间都是绿色,那就是遇到失效的问题了。
  • 最后,hardware layers使用GPU内存,你当然不想出现内存泄漏的问题。所以你应该在必要的时候再去使用hardware layers,就想播放动画时。

这里也没有硬性规则。Android渲染系统是非常复杂的。就像所有性能问题一样,测试才是关键。通过使用“显示硬件层更新”开发者选项来确定layers问题之后,再优化。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏androidBlog

Activity横竖屏切换的那些事

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

28820
来自专栏Hongten

android开发-TextView控件学习

public class MainActivity extends Activity{

15420
来自专栏非著名程序员

怎样设置EditText内部文字被锁定不可删除和修改,而文字只能在后面输入

在做项目的时候,我曾经遇到过这样的要求,就是跟百度贴吧客户端上的一样,在回复帖子的时候,在EditText中显示回复人的名字,而且这个名字不可以修改和删除,说白...

22160
来自专栏Android小菜鸡

Android自定义View——手写签批

  接到一个领导批示保留原笔迹的功能,类似于绘画板,用户打开后可以绘制,点击完成后以图片的形式保存在本地,并且显示绘制后图片,上传服务器,达到保留原笔迹的目的。...

17030
来自专栏分享达人秀

CheckBox和RadioButton使用大全

本期先来学习Button的两个子控件,无论是单选还是复选,在实际开发中都是使用的较多的控件,相信通过本期的学习即可轻松掌握。 一、CheckBox ...

468100
来自专栏酷玩时刻

android-iconify 使用详解

2、在java代码中通过使用一个IconDrawable为具有setIcon(Drawable drawable)方法的控件设置该字体图标

12620
来自专栏非著名程序员

Android学习第八弹之改变状态栏的颜色使其与APP风格一体化

导语:沉浸式状态栏,改变状态栏的颜色使之与APP风格一体化是不是感觉很漂亮,很美?其实实现这种效果并不难,google在4.4及以下提供了相关的方法。 我相信大...

19370
来自专栏分享达人秀

自定义ProgressBar打造酷炫进度条

Android系统默认的ProgressBar往往都不能满足实际开发需要,一般都会开发者自定义ProgressBar。 在Android开发中,...

1.3K50
来自专栏飞雪无情的博客

Android TextView小组件的使用--附带超链接和跑马灯效果

然后运行该应用就可以看到TextView的效果,是显示一行字:“Hello World, HelloTextView!”,这是因为新建的Hello项目自带的一个...

11350
来自专栏androidBlog

Android打造不一样的新手引导页面(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details...

15410

扫码关注云+社区

领取腾讯云代金券