文章

Android硬件加速

文章目录

前言

Android从3.0版本开始加入了硬件加速,这样就能够充分利用手机硬件GPU来提升界面的渲染效果。但是这种技术还有一些限制,比如有些开启了硬件加速的界面上无法使用Canvas的clipPath接口,一点调用就会抛出不支持的异常。现在来对硬件加速的小知识点做一些总结。

硬件加速

简单理解就是通过底层软件代码,将CPU不擅长的图形计算转换成GPU专用指令,由GPU完成。

Android3.0开始支持硬件加速,Android4.0默认启用硬件加速。

CPU和GPU

CPU : Central Processing Unit , 中央处理器,是计算机设备核心器件,用于执行程序代码。

GPU : Graphic Processing Unit , 图形处理器,主要用于处理图形运算,通常所说“显卡”的核心部件就是GPU。

硬件加速和软件加速

Android应用层的绘制主要有两种:软件绘制与硬件绘制。

软件绘制

CPU主导绘制,更新UI会重绘与脏区域相交的区域。

硬件加速

GPU主导绘制,提高显示刷新速度、更新UI只重绘脏区域,但是内存和电量消耗会比软件绘制大。

对应图形库

Skia : CPU 绘制 2D 图形; Open GL : GPU 绘制 2D / 3D 图形;

之后Android Q开始会使用 vulkan 来作为默认的图形库,有兴趣的可以提前了解下,这里不多赘述。

控制硬件加速(Controlling Hardware Acceleration)

如果您的应用程序仅使用标准视图和Drawables,则全局打开它不应导致任何不利的绘图效果。但是,由于所有2D绘图操作都不支持硬件加速,因此打开它可能会影响某些自定义视图或绘图调用。问题通常表现为不可见的元素,异常或错误渲染的像素。为解决此问题,Android为您提供了在多个级别启用或禁用硬件加速的选项。

android提供了以下四个级别的硬件加速控制:
  1. Application
  2. Activity
  3. Window
  4. View
Application级别

在应用的Android清单文件中,把下列属性添加到<application>元素中,能够开启整个应用程序的硬件加速:

<application android:hardwareAccelerated="true" ...>
Activity级别

如果不能再应用程序级别全局打开硬件加速,那么也可以在Activity级别上进行控制。在<activity>元素中使用android:hardwareAccelerated属性,能够启用或禁止Activity级别的硬件加速。以下示例启用全局的硬件加速,但却禁止了一个Activity的硬件加速:

<application android:hardwareAccelerated="true">
    <activity ... />
    <activity android:hardwareAccelerated="false" />
</application>
Window级别

如果需要更精细的控制,就可以使用下列代码来针对给定的Window来启用硬件加速:

getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
View级别

在运行时,可以针对一个独立的View对象使用下列代码来禁止硬件加速:

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

注意:目前不能在View级别开启硬件加速。View Layer除了禁止硬件加速以外,还有其他的功能,更多的相关信息请看下文的View layer。

判断一个View对象是否被硬件加速

有些时候,知道当前的View对象(尤其是自定义View)是否被硬件加速对应用程序来说是非常有用的。如果应用程序做了很多定制的绘图操作,并且不是所有的操作都会被新的渲染管道所支持,那么这种判断就特别有用。 有两种不同的方法来检查应用程序是否被硬件加速了:

View.isHardwareAccelerated()

如果View对象被绑定在硬件加速的Window,则返回true

Canvas.isHardwareAccelerated()

Canvas对象被硬件加速,则返回true 如果有必要在绘制代码中做这种检查,那么在可能的情况下,要使用Canvas.isHardwareAccelerated()方法来代替View.isHardwareAccelerated()方法。这是由于,当一个View对象跟一个被硬件加速的窗口绑定的时候,它依然能够使用使用一个非硬件加速的Canvas对象。例如,把一个View对象绘制到缓存中的一个位图时就会发生这种情况。

硬件加速使用建议

选择硬件加速来渲染2D图形可以有效改善性能,但是为了更有效的使用GPU,应该按照以下建议设计应用程序:

减少应用程序中View对象的数量

系统绘制越多的View对象,就会越慢。这种情况也适用于软件渲染管道。减少View对象数目是优化UI性能最有效的方式之一。

避免过度绘图

在彼此的顶部不要绘制太多的层。 移除那些完全被别的不透明View遮盖的View。 对于当前硬件的一个好的原则是,每帧的像素数不要大于屏幕上像素数的2.5倍(以位图的透明点阵数来计算)。

不要在绘图方法中创建渲染对象

一个常见的错误是每次调用渲染方法时创建一个新的Paint对象或Path对象。这样就会频繁地触发垃圾回收,导致硬件管道中的缓存和优化失效。

不要经常的编辑形状

对于复杂的形状,如路径和圆,是使用纹理掩码来呈现的。每次创建或修改路径,硬件通道都要创建一个新的纹理遮罩,这样会消耗大量的资源。

不要经常的编辑位图

每次改变位图内容,它都会被再次上传到GPU的纹理,以供下次绘制。

要小心的使用alpha相关的方法

当使用setAlpha()、 AlphaAnimation或ObjectAnimator,让一个View对象半透明时,需要双倍填充率来渲染到离屏缓存。当在一个大的View对象上应用透明效果时,要考虑把View对象的层类型设置为LAYER_TYPE_HARDWARE。

参考文章

  1. Android9.0 硬件加速(一)-开篇
  2. Android 硬件加速》、
  3. Android文档-硬件加速
发表评论