API Guide—Hardware Acceleration硬件加速


API Guide—Hardware Acceleration官方原文地址:

http://developer.android.com/guide/topics/graphics/hardware-accel.html

http://blog.csdn.net/cj1029/article/details/46274203

硬件加速

从Android 3.0的(API级别11)开始,Android的2D渲染管道支持硬件加速,这意味着所有View 的canvas的绘制都会使用GPU,这也会导致app应用将消耗更多的内存。

在API >= 14上,硬件加速是默认开启的,如果app程序使用的都只是标准的View和Drawable,则全局都打开硬件加速,是一定不会有任何副作用的。但是,由于硬件加速不支持所有的2D绘图操作,开启硬件加速可能会影响自定义View或绘图调用,常见的问题表现为View元素不可见,异常或像素渲染错误等。为了解决这个问题,Android允许开发者在多个层级上自行选择启用或禁用硬件加速。


硬件加速的级别

Application级别

在manifest文件 tag下添加hardwareAccelerated属性,控制整个应用程序是否开用硬件加速

Activity级别

如果app程序部分Activity启用硬件加速会有副作用,则可以通过在manifest文件 tag下添加hardwareAccelerated属性来关闭这些Activity的硬件加速

Window级别

如果需要更细粒度的控制,还可以通过以下代码启用一个窗口的硬件加速:

注意: 目前窗口级别不支持关闭硬件加速

View级别

更细粒度的,还可以在运行时关闭一个View的硬件加速,代码如下:

注意: 目前可以关闭View级别的硬件加速,但是不能在View级别开启硬件加速,因为还依赖其他的设置


确定View是否处于硬件加速状态

有时是应用程序需要知道当前是否开启了硬件加速,尤其是有自定义视图的情况下,由于不是所有的自定义的绘制操作新的渲染管倒都支持,此时知道硬件加速是否开启就变得尤为有用。

目前有两种不同的方式来检查应用程序是否处于硬件加速状态:

如果这个验证是必须的,则建议在draw的函数中使用,因为如果一个View被attach到一个硬件加速的Window上,即使没有硬件加速的Canvas,它也是可以被绘制的。比如:将一个View以bitmap的形式进行缓存


Android的绘制模型

当硬件加速开启时,Android框架会采用了新的绘图模型,通过显示列表来把应用程序渲染到屏幕上。充分理解显示列表以及它们如何影响应用程序,同样有助于我们理解在没有启用硬件加速情况下Android是如何绘制View的。下面的详细介绍基于软件的绘图模型和基于硬件加速的绘图模型。

基于软件的绘图模型

在软件的绘图模型中,View绘制需要以下两个步骤:
1. Invalidate the hierarchy
2. 绘制hierarchy

当一个view内容发生变化时会调用invalidate() 更新UI,失效(invalidation)消息将会在整个视图层中传递,计算每个需要重绘的区域(即脏区域)。 然后Android系统将会重绘所有和脏区域有交集的view。不幸的是这个绘图模型有两个缺点:

  1. 每个绘制操作中会执行不必要的代码(过度重绘)。例如应用程序调用invalidate()重绘button,而button又位于另一个view之上,即使该view没有变化也会进行重绘
  2. 这个模型可能会掩盖掉应用程序中的一些bug导致其被发现不了。因为android系统会重绘与脏区域有交集的view,所以view的内容可能会在没有调用invalidate()的情况下重绘。这可能会导致一个view只有在其它view时失效才得到正确的行为。这种行为可能在每次修改应用的时候都会发生改变。因此,你需要一直调用invalidate在你的自定义控件上,不管那些涉及到重绘的代码是否修改了数据或状态

注意: android view 在属性值变化的时候会自动调用invalidate,比如一个TextView的颜色或者背景的变化

基于硬件加速的绘图模型

Android系统仍然使用invalidate()和draw()来更新UI绘制view,但在实际处理绘制上有所不同。
硬件加速下Android系统不会立即执行绘制命令,而是把它记录到显示列表,包含的视图层次的绘图输出。另一个优化就是Android系统只需记录和更新标记为脏(通过)的view。还有没有被invalidated的View可以简单地通过重新发行之前记录的显示列表来重绘。新的绘制模型包含三个步骤:
1. Invalidate the hierarchy
2. 记录和更新显示列表
3. 绘制显示列表

在这种模式下,你不能指望一个视图相交的肮脏的地区会执行其draw()方法。为了确保Android系统记录视图的显示列表,你必须调用invalidate(),否则会导致View不会刷新。

使用显示表也有利于动画性能,例如设置View的一些特殊的属性alpha或旋转,不需要invalidate目标View(它会自动完成)。这种优化也可以应用于所有显示列表的视图(当application硬件加速的时候)。举个例子:假设有一个LinearLayout,包含一个ListView和一个Button,listview在上Button上方。那么对于这个LinearLayout的显示列表应该是这样的:

假设你想改变ListView的透明度,在listview上调用了之后,则显示列表变为:

ListView复杂的绘制代码并未执行。取而代之的是,系统只更新了简单地更新了LinearLayout的显示列表。如果没有开启硬件加速,则list及其父亲的draw代码块都会被执行。


硬件加速不支持的绘图操作

硬件加速支持大多数2D渲染管道的Canvas的绘制操作。
下图描述了各种绘图方法硬件加速开始支持的api level:

如果应用程序因为这些特征缺失或限制收到影响,你可以通过关闭硬件加速,这不会影响到其他的地方使用硬件加速。


View Layer

在所有版本的Android,所有的View具有渲染到锁屏缓冲区的能力,或通过View的绘制缓存,或者调用. 锁屏缓冲区或者layers有几种用途,可以用来实现复杂Views的动画或者组合效果时提升动画效果。比如, 实现渐变效果通过 渲染view到layer,
再通过与一个不透明的参数混合显示到屏幕上。

在Android 3(API级别11开始),可以有更多的控制何时如何使用view的方法。这个API有两个参数:Layer的类型和一个可选的Paint,可以使用Paint参数应用到color filters,,特殊的混合模式,或者一个layer的不透明度。

View的layer类型有三种:

  • 默认类型,view正常的渲染,不会通过锁屏的缓冲区返回。
  • 硬件加速开启的情况下在硬件绘制模型中绘制成硬件纹理,若硬件加速未开启则和一样
  • 在软件渲染模型中渲染成Bitmap

layer的类型取决于需求:

  • 性能:
    使用硬件层类型来渲染一个View到纹理层,一旦视图被渲染成一层,其绘图代码不必执行,直到视图调用invalidate()执行。一些动画,如alpha动画,然后可以被直接应用到层,使用GPU来做是非常高效的。

  • 视觉效应:
    使用硬件或软件层型和涂料适用于特殊的视觉处理的观点。例如,你可以通过画一个黑白相间的视图。

  • 兼容性:
    使用一个软件层类型去强制渲染一个视图。如果一个被硬件加速的视图(例如,如果你的整个应用程序的硬件加速),就会出现
    渲染的问题,这是一个解决硬件渲染管线限制的简单的方法。


View Layer与动画

如果应用打开了硬件加速,硬件层可以提供更快和更平滑的动画。在每秒60帧运行一个处理大量绘图操作的复杂动画有时候是不太可能的。这时可以通过使用硬件层将View渲染硬件纹理。硬件纹理可以用于动画视图,消除View在动画时的不断重绘。如此View不会重绘除非改变View的属性,调用了,或者手动的调用,如果应用程序动画的流畅度达不到预期,可以考虑使在动画View上使用硬件图层。

当一个视图是由硬件层的支持,它的一些属性通过layer被合成到屏幕。设置这些属性将是非常高效的,因为不需要View 和重绘。下面列出的属性会影响layer合成的方式。调用这些属性的set方法是最佳的,不会造成view重绘。

  • alpha —-> 改变透明度
  • x, y, translationX, translationY —-> 改变layer位置
  • scaleX, scaleY —-> 改变layer大小
  • rotation, rotationX, rotationY —-> 三维空间中图层的方向
  • pivotX, pivotY —-> 改变layer的不动点

这些属性动画所使用的是。如果要访问这些属性,调用相应的或即可。例如修改alpha属性,调用 。下面的代码片段显示在绕Y轴旋转的3D一viewiew最有效的方法:

因为硬件层消耗显存,强烈建议只为动画期间开启,动画结束禁用。这一点可通过实现:

更多属性动画信息。


技巧与提示

切换到硬件加速的2D图形可以立即提高性能,但仍建议遵循以下推荐规范来设计应用程序以便有效地利用GPU

  • 减少应用程序中的View的数量
    需要绘制的视图越多,绘制的速度就越慢,对于基于软件的绘制模型也是一样的。减少视图是一个简单的方法来优化UI。

  • 避免过度重绘
    每个View的上面不要有太多的层次,移除View上面被其他View完全遮盖的View。如果需要在每个view上绘制好几层,请尝试把它们合并为一个单一的层。根据当前的硬件条件,一个较好的经验准则是每帧像素绘制次数不超过屏幕上每帧的像素数2.5倍(透明像素按位图计算)。【也是就说每个像素最多overdraw2.5次,关于overdraw】

  • 不要在draw方法中创建渲染对象
    一个常见的错误是,每一次渲染方法被调用的时候都创建一个新的或一个新的。这会迫使gc更加频繁,也会绕过硬件管道的缓存和优化。

  • 不要太过频繁的修改形状
    复杂的形状如,,每次都是通过纹理masks来渲染的,每次创建或者修改,这个硬件管道会创建一个新的mask,这个代价是十分昂贵的。

  • 不要太过频繁的修改Bitmap
    每次改变的内容,在下次绘制时都会被以一个GPU纹理重新upload

  • 谨慎使用alpha
    当使用,或者实现一个透明的View时,是会在一个双倍填充率的离屏缓冲区渲染。当在大量view上做渐变时,建议考虑视图的层类型设置为 LAYER_TYPE_HARDWARE

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2015年4月27日
下一篇 2015年4月27日

相关推荐