1、Hardware Acceleration 硬件加速Hardware Acceleration从 Android 3.0 (API level 11)开始, Android 2D 渲染管线能更好的支持硬件加速。硬件加速通过 GPU执行各种绘画操作。因为硬件加速需要消耗更多的资源,所以你的 App 需要更多的 RAM。开启硬件加速最简单的方法是在整个应用全局设置。如果应用只使用标准的 View 和 Drawable,全局设置不会产生不利的影响。然而,因为硬件加速不支持所有的 2D 绘制操作,开启会影响一些自定义 View或者绘制调用。问题显示为不可见的元素、异常,或者错误渲染像素。为了补救这些,
2、Android 提供给你选项开启或者关闭硬件加速在以下几个层面: Application Activity Window View如果你的应用执行自定义绘制,开启硬件加速,测试应用在实际的硬件设备上去查找问题。控制硬件加速你可以在以下层面控制硬件加速 Application Activity Window ViewApplication 层在你的 Android manifest 文件里,添加以下属性到标签里,针对整个应用开启硬件加速:Activity 层如果整个应用开启硬件加速表现的不稳定,你也可以针对单个 Activity 进行控制。在 Activity 层开启或者关闭硬件加速,你可以使用
3、 android:hardwareAccelerated 属性在标签内。下面是单个Activity 中关闭硬件加速的例子:Window 层如果你需要更细致的控制,可以在获得的 Window 里开启硬件加速:getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); 注: 在 window 层不能取消硬件加速。View 层通过下面代码,你可以在运行时关闭硬件加速:myView.setLayerType
4、(View.LAYER_TYPE_SOFTWARE, null);注:你不能在 view 层开启硬件加速。 View 面板有其他方法关闭硬件加速。更多详细内容请看 View 面板。判断 View 是否已经硬件加速有时候,知道一个应用当前是否硬件加速是非常有用的,尤其像自定义 View。这非常有用,当你的应用做大量的自定义绘制并且不是所有操作都支持新的渲染管道。有两个方法查看应用是否硬件加速: View.isHardwareAccelerated() 如果 View 附属于硬件加速的窗体,将会返回 true。 Canvas.isHardwareAccelerated() 如果 Canvas 已硬
5、件加速,将会返回 true。如果你一定要在绘制代码中进行这个查看,请尽可能用 Canvas.isHardwareAccelerated()代替View.isHardwareAccelerated()。当一个 View 附属于硬件加速窗体,它仍可以通过非硬件加速的Canvas 来绘制。这种情况,在实例化时,绘制一个 View 到 bitmap 中,为了缓存目的。Android 绘画模型当开启硬件加速,新的绘画模型利用显示列表在界面上渲染你的应用。 为了完全理解显示列表和对你的应用有怎样的影响,知道 Android 不通过硬件加速怎么样绘制 View 也很重要。下面的篇章阐述基于软件和基于硬件的绘
6、画模型。基于软件的绘画模型在软件绘画模型中,View 通过以下两个步骤被绘制: 使层次失效 绘制层次每当应用需要更新部分 UI 时,调用 invalidate()(或者它的变形)在任意需要改变内容的 view 里。这些失效信息被传播始终在 view 层,计算需要重绘的界面区域。然后,Android 系统绘制任意 view 在这些区域。不幸的是,这种模型有两个缺点: 第一,这种模型需要执行的大量的代码在每一次绘画。比如,如果你的应用在按钮里调用了invalidate() ,而且这个按钮在另外一个 view 之上,此时 Android 系统会重绘这个 view,即时它没有发生改变。 第二个问题是绘
7、画模型会隐藏你应用的错误。从 Android 系统开始重绘 view,当他们与脏区域融合时,你改变的 view 的内容可能会被重绘即时 invalidate()没有被调用。此时,你依赖于另外一个view 使之失效来达到合适的反应。这个反应会在任何时候改变在你修改你的应用时。因此,你需要一直调用 invalidate()在你的自定义 view 上,无论你修改数据或者影响你 view 绘画代码的声明。注: Android view 当它的属性改变时,自动调用 invalidate() ,比如背景颜色或者文本框内容。基于硬件的绘画模型Android 仍使用 invalidate()和 draw()来
8、响应界面更新和视图渲染,不同的是控制当前绘制。Android 系统将他们记录在显示列表来代替马上执行绘画命令,它包含 view 层绘画代码的输出。另外一个优化是Android 系统只需对记录和更新显示列表,通过调用 invalidate()将 view 标记为。 还没失效的 View 通过重新运行之前的记录显示列表被重绘。这个新绘画模型包括三个阶段: 1、层失效 2、记录更新显示列表 3、绘画显示列表用此模式,你不能依赖与脏区域交叉的 view 来执行它的 draw() 。为了确保 Android 系统记录一个View 的显示列表,你必须调用 invalidate() 。 忘记这么做会导致视图
9、看起来一样,甚至在改变它后。一旦发生,这个 BUG 很容易被发现。使用显示列表也利于动画增强,因为设置特殊的属性,像透明度和旋转, 不需要使目标视图失效( 它自动完成) 。这个优化也适用于显示列表的视图 (你应用的任一视图都硬件加速) 比如,假设有个 LinearLayout 在Button 上有个 ListView。LinearLayout 的显示列表看上去这样:DrawDisplayList(ListView)DrawDisplayList(Button)假设你现在要改变 ListView 的不透明,在调用 setAlpha(0.5f)后,显示列表变成:SaveLayerAlpha(0.5
10、)DrawDisplayList(ListView)RestoreDrawDisplayList(Button)ListView 的设置代码没有被执行。系统只更新显示列表中更简单的 LinearLayout。在未开启硬件加速的应用中,列表的绘制代码在其父亲中还会被执行一次。不支持的绘画操作当启动硬件加速, 2D 渲染通道支持一般使用的画布绘画操作和一些较少使用的操作。所有的绘画操作被用于渲染程序,默认为 widget 和 layout,还有些高级应用比如反光和纹理平铺也是被支持的。下面是不被硬件加速的操作清单: Canvaso clipPath()o clipRegion()o drawPic
11、ture()o , int, int, android.graphics.Path, float, float, android.graphics.Paint) drawTextOnPath()o int, float, int, float, int, int, int, short, int, int, android.graphics.Paint) drawVertices() Painto setLinearText()o setMaskFilter()o setRasterizer() Xfermodeso AvoidXfermodeo PixelXorXfermode另外, 有些操
12、作在硬件加速开启后会发生变化 : Canvaso clipRect() : XOR, Difference and ReverseDifference clip modes are ignored. 3D transforms do not apply to the clip rectangleint, int, float, int, int, int, android.graphics.Paint) drawBitmapMesh() : colors array is ignored Painto setDither() : ignoredo setFilterBitmap() : fil
13、tering is always ono float, float, int) setShadowLayer() : works with text only PorterDuffXfermodeo PorterDuff.Mode.DARKEN will be equivalent to SRC_OVER when blending against the framebuffer.o PorterDuff.Mode.LIGHTEN will be equivalent to SRC_OVER when blending against the framebuffer.o PorterDuff.
14、Mode.OVERLAY will be equivalent to SRC_OVER when blending against the framebuffer. ComposeShader(郑州北大青鸟 http:/ ComposeShader can only contain shaders of different types (a BitmapShader and a LinearGradient for instance, but not two instances of BitmapShader )o ComposeShader cannot contain a ComposeS
15、hader如果你的应用受缺失属性和限制的影响,你可以关闭硬件加速,在你受影响的部分调用android.graphics.Paint) setLayerType(View.LAYER_TYPE_SOFTWARE, null) 。这个方法, 你仍可以利用硬件加速其他任一地方。查看 Controlling Hardware Acceleration 得到关于硬件加速的更多信息。View 层在 Android 的不同版本, view 已经有能力渲染进入屏幕缓存区内,无论是 view 的绘制缓存, 还是使用android.graphics.Paint, int) Canvas.saveLayer()。屏
16、幕缓存, 或层,有多种用途。你可以使用他们获得更好的性能,当动画组合视图或者需要应用复合效应。比如,你可以使用 Canvas.saveLayer()来实现消退效果来临时渲染一个 view 进入层,然后使用 opacity factor 合成到界面。Android 3.0 (API level 11)开始,你有更多的控制通过 android.graphics.Paint) View.setLayerType()方法,怎样或者什么时候使用 layers。这个 API 有 2 个参数:layer 的类型和可选的 Paint 对象,它阐明layer 怎么样合成。 你可以使用 Paint 参数使用滤色镜
17、, 特殊的混合模式 ,或者设置为不透明。view 可以使用三种 layer 类型的其中一种 : LAYER_TYPE_NONE:被一般渲染并且不会被进入屏幕缓存。这是默认行为。 LAYER_TYPE_HARDWARE:由硬件渲染到硬件纹理,如果应用开启硬件加速。如果未开启, 就同LAYER_TYPE_SOFTWARE。 LAYER_TYPE_SOFTWARE:由软件渲染到位图。The type of layer you use depends on your goal: Performance: 由硬件渲染到硬件纹理,一旦 View 被渲染到 layer,它的绘图代码不会被执行直到调用 inv
18、alidate()。有些动画,像透明度动画,直接放入 layer,由 GPU 完成非常有效率。 Visual effects:使用硬件或者软件 layer 类型和 Paint,对 view 应用特殊的视觉处理。比如,你使用 ColorMatrixColorFilter 绘制一个 view 为黑色或者白色。 Compatibility:使用软件 layer 类型促使 view 软件渲染。如果硬件加速的,有着渲染问题, 这是一个简单的方法来绕过限制的硬件渲染管道。(计算机学校 http:/ 层和动画开启硬件加速,硬件层提供提供更快的和更平滑的动画效果。当有很多绘图操作时,动画每秒 60 帧不是一直
19、能保持的。硬件层可以减轻这个,通过渲染为硬件纹理。硬件纹理可以优化 View,不再需要视图不断重绘本身。当你调用 invalidate()或者改变 view 属性时,view 才会重绘。如果动画显示的不够平滑,考虑开启硬件层在你使用的 View。当 view 进入后台硬件层,层被混合到界面,view 的属性被控制。设置这些属性很有效果,因为他们不需要 view 失效或者重绘。以下属性作用于混合层。 通过 setter 测试属性,获得最优效果: alpha: 改变层透明度 x, y, translationX, translationY: 改变层位置 scaleX, scaleY: 改变层大小
20、rotation, rotationX, rotationY: 改变层的三维定位 pivotX, pivotY: 改变层的转换源当 view 被作为 ObjectAnimator 启用时,这些属性被使用其他名字。如果你想使用这些属性,请调用适当的 setter 或者 getter。比如,为了改变 alpha 属性, 调用 setAlpha() 。下面的代码片段展示了最有效的方法旋转 viewiew 在 3D 的 Y 轴上:view.setLayerType(View.LAYER_TYPE_HARDWARE, null);ObjectAnimator.ofFloat(view, “rotatio
21、nY“, 180).start();因为硬件层消耗媒体资源,强烈介意你只在持续动画时开启,并且在动画结束时关闭。你可以使用animation listeners 完成:View.setLayerType(View.LAYER_TYPE_HARDWARE, null);ObjectAnimator animator = ObjectAnimator.ofFloat(view, “rotationY“, 180);animator.addListener(new AnimatorListenerAdapter() Overridepublic void onAnimationEnd(Animato
22、r animation) view.setLayerType(View.LAYER_TYPE_NONE, null););animator.start();更多信息,请看 Property Animation。要领和技巧开启硬件加速 2D 图像可以立即提高性能, 但你仍可以设计你的应用使用 GPU 性能,以下推荐:减少应用中视图的数量视图越多,速度越慢. 请求软件渲染通道也越慢。减少视图是优化 UI 的最简单的办法。避免透支不要在顶层绘制太多。去除那些被完全遮挡住的图层。如果你要绘制相互叠加的多个图层,考虑将他们合并为一个图层。不要在 draw 方法中创建 render 对象一个通常的错误是创
23、一个 Paint 对象或者 Path 对象,在任何时候 rendering 方法被调用。这使得垃圾收集器运行的更频繁,忽视缓存,在硬件通道优化。不要太频繁的改变图形图形实例化时,由 texture masks 被渲染。任何时候你改变路径, 硬件通道创建一个新的 mask,这是非常耗资源的。不要太频繁的改变位图任何时候你改变一个位图的内容,它作为 GPU 纹理重新被上传在下一次绘制时。使用透明度要小心当你通过 setAlpha()来改变透明度时, AlphaAnimation,或者 ObjectAnimator,在 off-screen buffer 被渲染,它两倍于使用 fill-rate。当应用 alpha 在非常大的界面上时,考虑设置视图属性LAYER_TYPE_HARDWARE.