从Android 3.0开始,Android 2D的绘制流程就设计为能够更好地支持硬件加速。使用GPU的View在Canvas上进行画的操作时都会使用硬件加速。在最新的Android版本里,图形硬件加速及绘制技巧得到了更好的提升。
1.Android 4.0硬件加速的使用
1.1 硬件加速的控制级别
启用硬件加速的最简单方法就是为整个系统打开硬件加速的全局设置。如果你的程序是标准View或者是Drawable 则硬件加速的全局设这并不会造成不良的影响。然而硬件加速并不支持所有2D画的操作,所以开启硬件加速可能会对使用自定义组件的应用程序造成影响,问题常常表现在不可见的元素异常和错误的像素渲染,为了解决这个问题Android可以让你选择启动或者禁用以下级别的硬件加速:Application,Activity,Window 和 View 。
1.1.1 Application级别
在你的Android Manifest文件中添加如下属性标记,以便为整个应用程序使用硬件加速。
<application android:hardwareAccelerated="true" ...>
1.1.2 Activity级别
如果你的应用程序不能在Application应用级别表现良好的话,则可以使用对Activity进行单独控制。要启动或者禁用一个Activity的硬件加速,你可以使用activity的android:hardwareAccelerated属性。下面的一个列子使整个Application启用硬件加速,但是对一个Activity禁止使用硬件加速。
<application android:hardwareAccelerated="true">
<activity ... />
<activity android:hardwareAccelerated="false" />
</application>
1.1.3 Window级别
如果你需要更细粒度的控制,你可以通过如下代码给window进行加速。
- getWindow().setFlags(
- WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
- WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
注意:现阶段你不能在Window级别对它禁用硬件加速。
1.1.4 View级别
我们可以对单独的View在运行时阶段禁用硬件加速。我们可以使用如下代码:
- myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
注意:现阶段不能够在View级别进行硬件加速。
1.2 判断一个View是否已经启用了硬件加速
有时候我们需要知道一个应用程序是否已经启用了硬件加速,特别是针对一些自定义控件。因为你的应用程序做了很多自定义“画”的操作,但并不是所有的过程都支持新的“画”的渲染过程。
有两种不同的方法来检查Application是否启用了硬件加速:
1.2.1 使用View.isHardwareAccelerated() 如果返回true则可以说明这个View所在的窗口已经启用了硬件加速。
1.2.2 Canvas.isHardwareAccelerated() 如果返回true则说明这个Canvas已经启用了硬件加速。
如果你必须要在你的绘画代码中进行是否已经加速的检查,如果可能的话请使用Canvas.isHardwareAccelerated()来代替View.isHardwareAccelerated()。当一个View是存在于一个已经加速的Windows上时,任然可以使用没有硬件加速的Canvas进行绘画,这常发生在,比如,当我们把一个View画到Bitmap上然后用作缓存。
1.3 为什么需要这么多级别的控制?
很明显,硬件加速能够带来性能提升,android为什么要弄出这么多级别的控制,而不是默认就是全部硬件加速呢?原因是并非所有的2D绘图操作支持硬件加速,如果您的程序中使用了自定义视图或者绘图调用,程序可能会工作不正常。如果您的程序中只是用了标准的视图和Drawable,放心大胆的开启硬件加速吧!具体是哪些绘图操作不支持硬件加速呢?以下是已知不支持硬件加速的绘图操作:
- Canvas
- Paint
另外还有一些绘图操作,开启和不开启硬件加速,效果不一样:
- Canvas
-
clipRect():
XOR
,Difference和ReverseDifference裁剪模式被忽略,3D变换将不会应用在裁剪的矩形上。
- drawBitmapMesh():colors数组被忽略
- drawLines():反锯齿不支持
- setDrawFilter():可以设置,但无效果
- Paint
- setDither(): 忽略
- setFilterBitmap():过滤永远开启
- setShadowLayer():只能用在文本上
- ComposeShader
- ComposeShader只能包含不同类型的shader (比如一个BitmapShader和一个LinearGradient,但不能是两个BitmapShader实例)
- ComposeShader不能包含ComposeShader
如果应用程序受到这些影响,您可以在受影响的部分调用setLayerType(View.LAYER_TYPE_SOFTWARE, null),这样在其它地方仍然可以享受硬件加速带来的好处