美文网首页
自定义View之绘制顺序和硬件加速

自定义View之绘制顺序和硬件加速

作者: 0246eafe46bd | 来源:发表于2021-06-24 19:16 被阅读0次

绘制流程

draw() 是View绘制过程的总调度方法,整个绘制过程都在draw()方法里

public void draw(Canvas canvas) { {
    drawBackground(canvas);  //绘制背景,无法重写
    onDraw(canvas); //绘制自身
    dispatchDraw(canvas); //绘制子View
    onDrawForeground(canvas); //绘制前景
}

ViewGroup 默认会绕过 draw() 方法,直接执行dispatchDraw(),来简化绘制流程,所以如果你自定义了某个ViewGroup 的子类(如LinearLayout)并且需要在它的除dispatchDraw() 以外的任何一个绘制方法内绘制内容,你可以调用View.setWillNotDraw(false) 来切换到完整的绘制流程

硬件加速

就是指把 View 中绘制的计算工作交给 GPU 来处理。

CPU把绘制的内容转换为GPU 的操作保存了下来,然后就把它交给 GPU,将 Canvas.drawXXX() 变成实际的像素这件事交给GPU处理。GPU本身比CPU更擅长于绘制的计算,硬件加速在界重绘的时候会优化绘制流程,避免一些重复操作。

硬件加速优化绘制流程

如果关闭硬件加速,Canvas绘制的内容会写进一个Bitmap,然后在渲染过程中,Bitmap的像素内容被渲染到屏幕,Canvas.drawXXX() 变成实际的像素这件事是由CPU处理的,当某个 View 调用 invalidate() 方法时,为了正确计算 Bitmap 的像素,和它相交的 View,这个 View 的父 View,甚至顶级 View都需要被调用 invalidate()来重绘。

如果开启硬件加速,绘制的内容会被转换成 GPU 的操作保存下来,相互独立,只需要把发生了改变的 View 调用 invalidate() 方法以更新它所对应的 GPU 操作就可以了,其他View不用改动

硬件加速的使用限制

Canvas 的部分方法不支持硬件加速

HardwareAccelerated.png

硬件加速的开启关闭

View.setLayerType(int layerType, @Nullable Paint paint)

参数layerType值可以为:

LAYER_TYPE_SOFTWARE:使用软件来绘制Layer,绘制到一个 Bitmap,并关闭硬件加速

LAYER_TYPE_HARDWARE:使用 GPU 来绘制Layer,绘制到一个 OpenGL texture,开启硬件加速

LAYER_TYPE_NONE:关闭Layer

setLayerType是给View设置 Layer(离屏缓冲) 的类型,作用是单独启用一块地方来绘制 View ,如果设置了 Layer ,View的绘制结果会被缓存下来,提高重绘效率

因此,在进行移动、旋转等(无需调用 invalidate())的属性动画的时候设置 Hardware Layer 可以提升动画的效率

        circleProgress.setLayerType(LAYER_TYPE_HARDWARE, null);
        val animator = ObjectAnimator.ofFloat(circleProgress, "rotationY", 0f, 45f)
        animator.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator) {
                circleProgress.setLayerType(LAYER_TYPE_NONE, null)
            }
        })
        animator.start()
        
        //或者使用ViewPropertyAnimator动画,使用withLayer()开启,这是一次性的,
        //在onAnimationEnd回调里会设置回原来的LayerType
        circleProgress.animate()
            .rotationY(45f)
            .withLayer()
LAYER_TYPE_HARDWARE_EXAMPLE.png

由于设置了 Layer ,View 在初次绘制时以及每次 invalidate() 后重绘时,需要进行两次的绘制工作(一次绘制到 Layer,一次从 Layer 绘制到显示屏),所以其实它的每次绘制的效率是被降低了的

相关文章

网友评论

      本文标题:自定义View之绘制顺序和硬件加速

      本文链接:https://www.haomeiwen.com/subject/cfegyltx.html