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
再渲染该layer
到Window
上。如果要渲染的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
问题之后,再优化。
- MongoDB固定集合
- MongoDB中各种类型的索引
- 敲一天代码了,轻松下吧,精彩 !看人潮如海
- MongoDB副本集其他细节
- 数据库表设计对性能的影响
- V部落博客管理平台开源啦! Vue+SpringBoot强强联合!
- SpringBoot+SpringSecurity处理Ajax登录请求
- MongoDB副本集配置
- MongoDB副本集搭建
- vhr部门管理数据库设计与编程
- SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题(六)
- 权限管理模块中动态加载Vue组件
- axios请求封装和异常统一处理
- SpringSecurity中密码加盐与SpringBoot中异常统一处理
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- java向mysql插入数据乱码问题解决
- java向数据库中插入中文出现乱码
- Flutter基础widgets教程-FractionallySizedBox篇
- 关于myeclipse控制台输出中文乱码的问题
- nutz 自定义查询 分页 取值
- jquery-uploadifyv3.2.1 文件上传插件 学习
- Flutter基础widgets教程-Icon篇
- Redis:持久化
- Flutter基础widgets教程-IconButton篇
- Flutter基础widgets教程-Image篇
- Go - 学习 grpc.Dial(target string, opts …DialOption) 的写法
- Flutter基础widgets教程-IntrinsicHeight篇
- Flutter基础widgets教程-Baseline篇
- springcloud本地开发的微服务如何调用远程k8s的微服务
- Flutter基础widgets教程-LimitedBox篇