本文译自:http://developer.android.com/guide/topics/graphics/hardware-accel.html
View层和动画
当应用程序被硬件加速的时候,硬件层能够传递更快、更平滑的动画。当播放具有复杂的绘图操作的动画时,以每秒60帧的速度播放不总是可能。这样能够通过使用硬件层把View对象呈现在硬件纹理中,可以缓解这种情况。硬件纹理能够被用于动画视图,这样在该View对象呈现动画时,就可以消除View对象所需要的重绘操作。直到View对象的属性发生变化时(invalidate()方法被调用),该View对象才会被重绘。如果在应用程序运行一个动画,并且没有获得想要的平滑结果,就要考虑在动画View上启用硬件层。
当一个View被硬件层返回时,通过层方法处理的某些属性会被合成到屏幕上。因为它们不需要让View对象失效和重绘,所以设置这些属性是非常高效的。下面列出了影响层被合成的方式。调用这些属性设置器,会导致失效处理的优化,并且不会对目标View对象进行重绘:
1. alpha:改变层的透明度;
2. x,y,translation,translation:改变层的位置;
3. scaleX,scaleY:改变成的尺寸;
4. rotation,rotation,rotationY:改变3D空间中层的方向;
5. pivotX,pivotY:改变层的变换起源。
这些属性是在用ObjectAnimator对象给View对象设置动画时所使用的名称。如果想要访问这些属性,就要调用相应的set或get方法。例如,要修改alpha属性,就要调用setAlpha()方法。下面的代码展示了在3D空间中围绕Y轴旋转View对象的最有效的方法:
view.setLayerType(View.LAYER_TYPE_HARDWARE,null);
ObjectAnimator.ofFloat(view,"rotationY",180).start();
因为硬件层会消耗显示内存,因此强烈推荐只在动画播放期间启用硬件层,并且在动画播放结束后就禁用该硬件层。能够使用动画监听器来完成这种操作:
View.setLayerType(View.LAYER_TYPE_HARDWARE,null);
ObjectAnimator animator =ObjectAnimator.ofFloat(view,"rotationY",180);
animator.addListener(newAnimatorListenerAdapter(){
@Override
publicvoid onAnimationEnd(Animator animation){
view.setLayerType(View.LAYER_TYPE_NONE,null);
}
});
animator.start();
更多的属性动画的信息,请看Property Animation(http://developer.android.com/guide/topics/graphics/prop-animation.html)
提示和技巧
切换到硬件加速的2D图形能够有效改善性能,但是依然要通过以下推荐的方式来设计应用程序,以便有效的使用GPU:
1. 减少应用程序中View对象的数量
系统绘制越多的View对象,就会越慢。这种情况也适用于软件呈现管道。减少View对象的有效方法之一就是优化UI。
2. 避免过度绘图
在彼此的顶部不要绘制太多的层。因为删除View时要同时删除遮盖在该View对象之上所有其他的不透明的View对象。如果需要绘制几个图层,要尽量在上面采用合成模式,考虑把它们合并成一个层。一个好的规则是:每帧的像素数不要大于屏幕上像素数的2.5倍(以位图的透明点阵数来计算)。
3. 不要在绘图方法中创建呈现对象
一个常见的错误时每次调用呈现方法时创建一个新的Paint对象或Path对象。这样就会强制频繁的运行垃圾回收,并且会绕过硬件管道中的缓存和优化。
4. 不要经常的编辑形状
对于复杂的形状,如路径和圆,是使用纹理掩码来呈现的。每次创建或修改路径,硬件通道都要创建一个新的掩码,这样会消耗大量的资源。
5. 不要经常的编辑位图
每次改变位图内容,都会在下次绘图时再次更新GPU的纹理。
6. 要小心的使用alpha相关的方法
当使用setAlpha()、AlphaAnimation或ObjectAnimator,让一个View对象半透明时,会需要双倍填充率的屏幕外缓存。当在一个大的View对象上应用透明效果时,要考虑把View对象的层类型设置为LAYER_TYPE_HARDWARE。