03-硬件加速

前言

在讲 Canvas 绘图之前,我们先来简单介绍下硬件加速,因为开启硬件加速后,Canvas的某些方法会失效,这时需要关闭硬件加速才能看到效果。

从 Android 3.0(API 级别 11)开始,Android 2D 渲染管道支持硬件加速,也就是说,在 View 的画布上执行的所有绘制操作都会使用 GPU。启用硬件加速需要更多资源,因此应用会占用更多内存。如果最低 版本为 14 及更高级别,则硬件加速默认处于启用状态。

Q:什么是硬件加速?

A:所谓硬件加速,指的是把某些计算工作交给专门的硬件来做,而不是和普通的计算工作一样交给 CPU 来处理。这样不仅减轻了 CPU 的压力,而且由于有了「专人」的处理,这份计算工作的速度也被加快了。这就是「硬件加速」。

而对于 Android 来说,硬件加速有它专属的意思:在 Android 里,硬件加速专指把 View 中绘制的计算工作交给 GPU 来处理。进一步地再明确一下,这个「绘制的计算工作」指的就是把绘制方法中的那些 Canvas.drawXxx() 变成实际的像素这件事。

怎么就加速了?

  • 用了 GPU(自身的设计本来就对于很多常见类型内容的计算,例如简单的圆形、简单的方形等具有优势),绘制变快了

  • 绘制机制的改变,导致界面内容改变时的刷新效率极大提高

如果想了解更多关于硬件加速的底层原理,可以查看这篇文章理解Android硬件加速原理的小白文

硬件加速开关

  • Application
1
    <application android:hardwareAccelerated="true" ...>
  • Activity
1
2
3
4
    <application android:hardwareAccelerated="true">
        <activity ... />
        <activity android:hardwareAccelerated="false" />
    </application>
  • Window
1
2
3
4
5
    //window层级,只能开启,无法进行关闭
    window.setFlags(
      WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
      WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
    )
  • View
1
2
    //控制当前view图层是否使用硬件加速,如果应用总体未开启硬件加速,那么即便设置type为LAYER_TYPE_HARDWARE,也无法开启硬件加速
    view.setLayerType(View.LAYER_TYPE_SOFTWARE, null)

如何判断当前是否开启硬件加速?

1
2
3
    view.isHardwareAccelerated();//1. 判断当前是否开启硬件加速

    canvas.isHardwareAccelerated();//2. 判断当前是否开启硬件加速

由于通常情况下,canvas是绘制的载体,所以应该通过canvas进行判断

硬件加速使用限制

硬件加速虽好,但开启硬件加速后,绘制Canvas的某些方法失效或无效,在使用时需要注意这些方法:

  • Canvas

    方法 开始支持API版本
    drawBitmapMesh()(颜色数组) 18
    drawPicture() 23
    drawPosText() 16
    drawTextOnPath() 16
    drawVertices()
    setDrawFilter() 16
    clipPath() 18
    clipRegion() 18
    clipRect(Region.Op.XOR) 18
    clipRect(Region.Op.Difference) 18
    clipRect(Region.Op.ReverseDifference) 18
    clipRect()(通过旋转/透视) 18
  • Paint

    方法 开始支持API版本
    setAntiAlias()(适用于文本)(颜色数组) 18
    setAntiAlias()(适用于线条) 16
    setFilterBitmap() 17
    setLinearText()
    setMaskFilter()
    setPathEffect()(适用于线条) 28
    setShadowLayer()(除文本之外) 28
    setStrokeCap()(适用于线条) 18
    setStrokeCap()(适用于点) 19
    setSubpixelText() 28
  • Xfermode

    方法 开始支持API版本
    PorterDuff.Mode.DARKEN(帧缓冲区) 28
    PorterDuff.Mode.LIGHTEN(帧缓冲区) 28
    PorterDuff.Mode.OVERLAY(帧缓冲区) 28
  • Shader

    方法 开始支持API版本
    ComposeShader 内的 ComposeShader 28
    ComposeShader 内相同类型的着色器 26
    ComposeShader 上的本地矩阵 18
  • Scale

    方法 开始支持API版本
    drawText() 18
    drawPosText() 28
    drawTextOnPath() 28
    简单的形状 17
    复杂的形状 28
    drawPath() 28
    阴影层 28

    简单形状,是指使用 Paint 发出的 drawRect()drawCircle()drawOval()drawRoundRect()drawArc()(其中 useCenter=false)命令,该 Paint 不包含 PathEffect,也不包含非默认联接(通过 setStrokeJoin()/setStrokeMiter())。这些绘制命令的其他实例都属于上表中的“复杂”形状。