美文网首页
【Android渲染】为什么alpha渲染性能低?

【Android渲染】为什么alpha渲染性能低?

作者: 二手认知 | 来源:发表于2020-12-06 00:17 被阅读0次

    开门见山

    1. 多次写入像素

    在渲染不透明的像素时,只需要写入一次

    在渲染透明像素时,每个像素至少需要写入两次

    • 第一次是之前的像素值
    • 第二次把之前的颜色与设置的不透明度做混合,产生一个新的颜色值,写入这个新的颜色值。

    我们看到的一层下面有另一层的半透明效果,对于屏幕来说就是一个混合后的具体的颜色值。


    2. 指令重排无效

    发给RenderThread的DisplayList,里面的内容是按照View层级来排列的,默认顺序执行,但这样性能并不好:

    分治、归并的思路可以提高性能,大家都听过指令重排序,把相同的指令一起执行、合并成一次操作执行,这样性能肯定是更好的,经过优化,绘制的流程如下:

    很多内容一次绘制成功,非常高效。只是有一个问题,其实上面的例子中,背景item并不是一次性渲染的,原因是因为出现了重叠(overlap),为了确保重叠后的alpha是正确的,这里的渲染只能串行执行,而不能归并。

    我们发现,正确性还是Android默认方案的第一权重;在第1点中提到过,alpha渲染,底层是在原像素上做blending,要依次渲染。

    我们看到,大部分的渲染操作都可以享受指令重排序、归并批处理的高性能,但alpha渲染被排除在外了。

    3. 灾难情况: ViewGroup的alpha渲染

    在动画中,经常需要更改ViewGroup的透明度实现淡入淡出效果。这时候,事情有了一些变化,如果沿用之前的绘制方式(每个子View逐个透明度绘制)会出现一个问题:

    重叠的部分,不透明度会叠加(如下图右侧).

    我们想要的效果是下图左侧,而不是右侧。

    这个问题应该怎么解决呢?Android渲染团队当然也意识到这个问题,他们的解决方案是:

    • 绘制一帧未做alpha变换的数据到内存中
    • 然后把这一帧的数据做alpha处理之后,渲染到屏幕

    这个方案确实可以解决上面的UI异常问题。只是,他导致了一次整个View Hierarchy的重新绘制,每次ViewGroup 的alpha变换都要重绘一帧数据,如果我在执行一个动画,那岂不是性能灾难?

    于是问题就来了:

    这一帧数据为什么要重新绘制?刚刚渲染的不就是这一帧吗?

    同学你说的很对,这一帧确实生成过了,只是被丢弃了。毕竟它会占用不小的内存,如果不知道是否有用,默认在会之后丢弃。

    我们优化的方向,就是使用缓存数据,空间换时间。具体的执行调用如下API:

    //before API 16
    setLayerType(View.LAYER_TYPE_HARDWARE, null);//before alpha animation
    setLayerType(View.LAYER_TYPE_NONE, null);//after alpha animation
    
    //from API 16
    ViewPropertyAnimator.alpha(0.0f).withLayer();//manage layer type automatically
    

    刚刚我们谈到,问题的出现是因为重叠部分的UI出现了异常,如果你的确信不会出现UI重叠,或者(为了更好的渲染性能)可以接受因此产生的UI问题,可以重写View的hasOverlappingRendering方法,结果返回false, 它会带来渲染性能的提升。

    class MyView extends View {
    
        @Override
        public boolean hasOverlappingRendering() {
            return false;
        }
    }
    
    性能对比图

    以上。


    Reference

    https://www.youtube.com/watch?v=zdQRIYOST64
    https://www.youtube.com/watch?v=wIy8g8yNhNk&feature=emb_logo

    相关文章

      网友评论

          本文标题:【Android渲染】为什么alpha渲染性能低?

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