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
问题之后,再优化。
- Spring data 如何定义默认时间与日期
- Spring boot with Oauth2
- Elasticsearch Cluster 安装与配置
- 数据库结构版本控制
- 【Golang语言社区】LollipopGo框架之商城项目--路由设置
- "LollipopGo/library/lollipop/common" 测试3
- "LollipopGo/library/lollipop/common" 测试2
- Golang语言并发技术详解
- Golang语言社区--Go基础课程第一节聊聊Go语言
- Spring boot with ELK(Elasticsearch + Logstash + Kibana)
- 数据库与缓存
- 通过 Proxy 汉化 restful 接口
- 学习笔记CB005:关键词、语料提取
- Eclipse油藏模型解析程序
- 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 文档注释
- Spring Security权限框架理论与简单Case
- leetcode树之N叉树的前序遍历
- Spring Security 中的 hasRole 和 hasAuthority 有区别吗?
- python常见的import导包技巧
- 真正了解贪心算法,这是一篇精华入门总结...
- MGR修改max_binlog_cache_size参数导致异常
- 【技术创作101训练营】TensorFlow Lite的 GPU 委托(Delegate)加速模型推理
- 弄懂这 5 个问题,拿下 Python 迭代器!
- 1500字,8个问题,彻底理解堆!
- Python画王者荣耀英雄能力雷达图
- Python语言的精华:Itertools库
- MySQL为什么lsof会看到这么多临时文件
- IE浏览器主页被劫持,如何解决主页被篡改问题?
- 参与国际化项目一定要遵循的java命名规范
- 威胁事件告警分析技巧及处置(二)