Android基础知识

Android 优化之硬件加速

2021-02-01  本文已影响0人  tandeneck

原理

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

当目标 API 级别大于等于 14 时,硬件加速默认开启。

控制硬件加速

我们可以在以下 4 个级别控制硬件加速:

<application android:hardwareAccelerated="true" ...>
 <application android:hardwareAccelerated="true">
        <activity ... />
        <activity android:hardwareAccelerated="false" />
    </application>
    window.setFlags(
            WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
            WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
    )
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null)

DisplayList

DisplayList 是一个基本绘制元素,包含元素原始属性(位置、尺寸、角度、透明等),当 view 的一些属性改变(scale 、rotate、alpha、translate),只需把属性更新给 GPU,不需要生成新的 DisplayList。

RenderNode

一个 RenderNode 包含若干个 DisplayList,通常一个 RendeNode 对应一个 View,包含 View 及其 View 的所有 DisplayList。

软件绘制与硬件绘制

  1. 场景1中,无论是否开启硬件加速,遍历 view 树并都会走 Draw 路径。硬件加速后 Draw 路径不做实际绘制工作,只是构建 DisplayList,复杂的绘制计算被 GPU 分担。

  2. 场景2 中,TextView 设置前后尺寸位置不变,不会触发重新 Layout。

判断 View 是否经过硬件加速

ViewLayer

View Layer 又称离屏缓冲,它的作用是单独开辟一块地方来绘制 view,
前面提到 View 不能启用硬件加速,只能停用硬件加速具体展开情况如下:

当我们设置了 View Layer 后,绘制操作会被缓存下来,而且缓存的的是最终的绘制结果。这样,View 的重绘效率进一步提升:只要绘制的内容没有变,那么无论是软件绘制(CPU)还是硬件绘制(GPU),它们都不用重新计算,只用之前的缓存的绘制结果即可。(可以对标图片加载缓存来理解。)

硬件加速与动画

动画在 App 中是必不可少的,而动画又是相对消耗性能的,卡顿的动画严重影响用户体验。幸运的是,我们可以通过设置 Hardware Layer 的方式提升动画的效率,代码如下:

view.setLayerType(View.LAYER_TYPE_HARDWARE, null)
    ObjectAnimator.ofFloat(view, "rotationY", 180f).apply {
        addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator) {
                view.setLayerType(View.LAYER_TYPE_NONE, null)
            }
        })
        start()
    }

设置 Hardware Layer 会占用视频内存,因此我们应该只在动画播放期间启用。之所以能提高动画效率是因为在进行移动、旋转、缩放、透明度(无需调用 invalidate)的动画时候,View 本身并没有发生改变,只是它的位置或者角度改变了,而这种改变是可以由 GPU 通过简单计算就完成的,并不需要重绘整个 View。与之对应的,如果我们开启的是 自定义属性绘制的动画或者手动调用了 invalidate,这种设置方式是没有用的。

参考

上一篇下一篇

猜你喜欢

热点阅读