从Android 3.0开始(API L11),Android开始全面使用硬件加速来进行2D渲染,硬件加速是指Android中在View上进行绘制的图形图像都使用GPU来进行绘制,使用硬件加速,在大部分时候都让绘制更加流畅,但付出的代价是需要消耗更多的内存资源。
硬件加速在API L14之上是默认开启的,对于基本的View绘制,通过硬件加速可以增加绘图的流程性,但是要注意的是,并不是所有的2D图形绘制API都支持硬件加速。
通过开发者选项中的“强制进行GPU渲染”,用户可以为全局打开硬件加速。在3.0 以上的Android中,系统已经对大部分动画都进行了硬件加速。
由于硬件加速对某些2D绘图API的不支持,所以Android系统提供了四种级别的控制方式。
在应用的Android清单文件中,把下列属性添加到<application>元素中,来开启整个应用程序的硬件加速,代码如下所示:
android:hardwareAccelerated="true"
比整个App范围稍小,我们可以在Activity范围内进行控制,代码如下所示:
android:hardwareAccelerated="true"
getWindow().setFlags( WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
但是对Window来说,Android无法禁止硬件加速。
View级别是用的最多的控制硬件加速的级别,我们可以通过如下所示的代码来禁止硬件加速:
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
与Window级别相反,我们无法在View级别开启硬件加速。
View.isHardwareAccelerated() Canvas.isHardwareAccelerated()
基于软件的绘图模式在重绘View时,需要如下两个过程:
这种方式隐藏了绘制中的bug,例如上面的例子中,由于ViewA、ViewB相互重叠,有需要重绘的the dirty region,那么如果B忘记了进行重绘的逻辑,那么A进行重绘的时候,就会将B重绘,也就是说使用错误的行为来得到了正确的现象。正是因为这个原因,开发者需要保证在View需要发生重绘时,调用正确的invalidate()方法。
使用这种方式,就可以避免软件绘图中第二点的bug。
例如,假设有一个包含了一个Button对象的ListView对象的LinearLayout布局,那么LinearLayout布局的显示列表如下:
1. DrawDisplayList(ListView);
2.DrawDisplayList(Button)
假设现在要改变ListView对象的不透明度,那么在调用ListView对象的setAlpha(0.5f)方法时,显示列表就包含了以下处理:
1.SaveLayerAlpha(0.5);
2.DrawDisplayList(ListView);
3. Restore;
4.DrawDisplayList(Button)
如果应用程序受到这些错误的功能或限制的影响,那么能够通过调用setLayerType(View.LAYER_TYPE_SOFTWARE, null)方法针对应用程序受到影响的部分来关闭硬件加速。
具体哪些方法不支持硬件加速可以参考Google开发者网站上的这篇文档 http://developer.android.com/guide/topics/graphics/hardware-accel.html
在所有的Android版本中,View都可以通过Canvas.saveLayer()方法来获得离屏缓冲的能力,离屏缓冲区或层有多种用途,特别是在呈现复杂的动画或使用组合效果时,能够获得更好的性能。例如,使用Canvas.saveLayer()可以实现淡入淡出的效果,先暂时把一个View对象渲染在一个层中,然后把它和不透明因子合成到屏幕上显示。
从Android3.0(API Level 11)开始,用View.setLayerType()方法使用层的方式和时机会更多的控制。这个API需要两个参数:一个是层的类型,另一个是可选的,用于描述层应该如何被合成的Paint对象。能够使用这个Paint对象来进行颜色过滤、特殊的混合模式、或者层的透明度。View对象能够使用以下三种层类型:
使用哪种层的类型,依赖以下目标:
当应用层使用硬件加速的时候,手机显示硬件可以让动画、显示效果更加平滑。如果你的动画效果不够流畅,那么就需要考虑在View层面上使用硬件加速来进行优化。在Android中,有些视图操作使用硬件加速是非常高效的,因为这些操作不需要让对象失效后重绘,例如:
1. alpha:改变层的透明度
2. x,y,translation,translation:改变层的位置
3. scaleX,scaleY:改变成的缩放
4. rotation,rotation,rotationY:改变3D空间中视图的方向
5. pivotX,pivotY:改变层的变换控制点
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(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { view.setLayerType(View.LAYER_TYPE_NONE, null); } }); animator.start();
当我们使用硬件加速时,会消耗更多的内存(将近4倍),如果分给应用的内存没有这么多,那么就会从系统剩于内存中进行划分,因此,硬件加速不适用于系统的核心进程。好的应用,应该在硬件加速(GPU)与软件绘制(CPU)中找到平衡点。
另外,需要注意的是,App中进行UI渲染是无法使用并发的,多核心无法带来显示上的性能提升。同时,分辨率也是影响流畅度的一个非常重要的方面,为了能够在更高的分辨率上进行流畅的绘制效果,那么就需要使用更加强大的GPU进行渲染。
原文地址:http://blog.csdn.net/eclipsexys/article/details/44228403