关于GPU过度绘制的那些误解

提到防止页面卡顿,大家首先想到的会是页面层级嵌套过多导致过度绘制。那么达到什么程度页面才算过度绘制呢?

绘制限制

手机屏幕由很多像素点组成,通过变换每个像素点的颜色,形成各种各样的图像。GPU控制的一块缓冲区中,这块缓冲区叫做Frame Buffer(也就是帧缓冲区)。可以简单理解成一个二维数组,数组中的每一个元素对应着手机屏幕上的一个像素点,元素的值代表着屏幕上对应的像素点要显示的颜色。优化屏幕画面不断变化,需要这个buffer不断地更新数据,一个FrameBuffer肯定是应接不暇的,因此GPU除了Frame Buffer,用以交给手机屏幕进行绘制外,还有一个缓冲区,叫Back Buffer,这个Back Buffer 用以交给你的应用,让你往里面填充数据。GPU会定期交换Back Buffer和Frame Buffer,也就是让Back Buffer 变成Frame Buffer交给屏幕进行绘制,让原先的Frame Buffer变成Back Buffer交给你的应用进行绘制。交换的频率也是60次/秒,这就与屏幕硬件电路的刷新频率保持了同步。

上面说了刷新频率是1000/60hz = 16ms,这就要求CPU和GPU每秒要有处理60帧的能力,一帧花费的时间在16ms内。因此屏幕刷新的全部逻辑操作也需要在16ms内完成,否则就会出现画面丢失造成卡顿。

CPU过度绘制

指屏幕上的一个像素被绘制多次(超过一次) 但是用户看到的只有最顶层绘制的内容

(1)蓝色1x过度绘制

(2)绿色2x过度绘制

(3)淡红色3x过度绘制

(4)红色4x过度绘制(4次及以上)

App的验收标准:

(1)控制过度绘制为2x

(2)非强制GPU的情况下,无红色区域,即无4x过度绘制情况

(3)浅红色区域总面积不超过屏幕的1/4大小

检测工具

开发者选项->调试GPU过度绘制

关于误解

大家都知道复杂布局的过度嵌套如LinearLayout嵌套过多层的LinearLayout就会导致过度绘制真的是这样吗?

多层嵌套pk无嵌套

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="50dp">
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="50dp">
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:padding="50dp">
                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@mipmap/album_camera_icom" />
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="多层嵌套"
                    android:textColor="@color/black"
                    android:textSize="22sp"
                    android:textStyle="bold" />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/album_camera_icom" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="无嵌套"
        android:textColor="@color/black"
        android:textSize="22sp"
        android:textStyle="bold" />
</LinearLayout>

                                                                

经过手机自带GPU过度绘制检测运行结果如上图,可以看出两者并无差异,那么是什么使它们产生差异呢。下面我们分别为上述LinearLayout添加背景色。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:gravity="center"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:orientation="vertical"
        android:padding="50dp">
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:orientation="vertical"
            android:padding="50dp">
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@color/white"
                android:orientation="vertical"
                android:padding="50dp">
                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@mipmap/album_camera_icom" />
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="多层嵌套"
                    android:textColor="@color/black"
                    android:textSize="22sp"
                    android:textStyle="bold" />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:gravity="center"
    android:orientation="vertical">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/album_camera_icom" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="无嵌套"
        android:textColor="@color/black"
        android:textSize="22sp"
        android:textStyle="bold" />
</LinearLayout>

                                                                    

当给每一个LinearLayout添加背景色时多层嵌套出现了明显的过度绘制情况。

总结

1.多层嵌套未必会导致GPU过度绘制。

2.GPU过度绘制有一种必然是页面多层嵌套。

3.导致GPU过度绘制产生是一个像素多次绘制,要想避免这种情况添加背景需谨慎。

4.多用ConstraintLayout减少层级嵌套。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值