【Android 性能优化】布局渲染优化 ( 过渡绘制 | 自定义控件过渡绘制 | 布局文件层次深 | GPU 过渡绘制调试工具 | 背景过度绘制 )





一、 过度绘制



过渡绘制 :


① 过渡绘制 : GPU 绘制图像时 , 会从底层到上层逐层绘制 , 底层的图像会被上层覆盖 , 底层图像无法显示给用户观看 , 但还是会占用绘制时间 , 这样就造成了时间上的浪费 , 甚至导致整个渲染过程超过 16 ms ;


② 过渡绘制的示例 : 打个比方 , 给墙刷大白 , 先刷一遍绿色的 , 再刷一遍蓝色的 , 最后再刷白色的 , 很明显先刷的两遍是无用的 , 但是耗费了很多时间 , GPU 的过渡绘制也是这个原理 , 底层绘制了很多重叠覆盖的图像 , 花费了时间最终并不展示给用户观看 ;





二、 过度绘制两种情况 ( 自定义控件 | 布局文件 )



Android 中 GPU 过度绘制情况 : 自定义控件 , 布局文件 ;


① 自定义组件 : 在自定义 View 组件中 , 实现的的 onDraw 方法使用 Canvas 绘制了很多重叠的元素 ; 如绘制 Bitmap 后 , 又在该 Bitmap 上又绘制了一个矩形 , 这样矩形覆盖了 Bitmap , 这两个图像都要被 GPU 渲染 , 这样就增加了渲染时间 ;


② 布局层次深 : 在普通的布局文件中 , 布局嵌套很多 ; 如外层的 RelativeLayout , 内层嵌套了 LinearLayout , 在线性布局中又嵌套了 FrameLayout , 布局嵌套会导致很多组件的重叠 ; 对于每个组件 , CPU 都会将该组件对象转为向量图 , 传递给 GPU 渲染 , 重叠图像过多 , 显然会使 GPU 过渡绘制 ;


设置透明背景 , 或者设置组件 Gone , 就不会绘制该组件





三、 过度绘制调试





1. 打开过渡绘制调试工具


开发者选项中 , 有 “调试 GPU 过渡重绘” 选项 , 打开该选项 , 选择 “显示过渡绘制区域” , 即可查看过渡绘制情况 ;

在这里插入图片描述


选择 第二项 , “显示过渡绘制区域” , 即可查看过渡绘制情况 ;

在这里插入图片描述



2. 过渡绘制调试中不同颜色的含义


组件上各个颜色代表的含义 : 打开过渡绘制调试工具后 , 组件上有不同的颜色 ;


① 蓝色 : GPU 过度绘制了 1 1 次 , 没有过渡绘制 ;

② 浅绿色 : GPU 过度绘制了 2 2 次 ;

③ 浅红色 : GPU 过度绘制了 3 3 次 ;

④ 深红色 : GPU 过度绘制了 4 4 次及 4 4 次以上 ;

在这里插入图片描述

在这里插入图片描述


一般情况下蓝色 , 和浅绿色是可以接受的 , 红色 , 深红的区域绝对不能大范围出现 ;



3. 过渡渲染示例


这是 Android 的设置界面 , 大部分是蓝色 , 或浅绿 , 浅红色只占很小的部分 ;
在这里插入图片描述





四、 背景过度绘制



1 . 背景设置 :


① 设置背景 : 设置了背景 , 图片或颜色值 , 绘制增加 1 1 次 ;

② 透明背景 : 背景透明 , 不增加绘制次数 , 绘制增加 0 0 次 ;

③ 主题背景 : 在主题中设置了背景 , 也会增加 1 1 次绘制 ;


如果同时设置布局的背景和主题背景 , 此时会绘制 2 2 次 ;

删除一次背景设置 , 这里建议删除主题的背景 ;



2 . 删除主题背景 :


① 使用代码删除 : 调用 getWindow().setBackgroundDrawable( null ) 方法 , 删除背景 , 该方法调用调用必须 在 super.onCreate 之后, 在 setContentView 之前 ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 删除背景, 该调用必须在 super.onCreate 之后, setContentView 之前
        getWindow().setBackgroundDrawable(null);

        setContentView(R.layout.activity_main);
}

② 主题中删除 ( 建议 ) : 在主题中设置 <item name=“android:windowBackground”>null</item> 元素 , 然后 Activity 使用该主题 , 即可避免背景二次重绘 ;

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

        <!-- 设置应用启动时默认显示的图片 , 这样比白屏/黑屏体验好一些 -->
        <!--<item name="android:windowBackground">@mipmap/ic_launcher</item>-->

        <!-- 将背景设置成透明的 -->
        <!--<item name="android:windowIsTranslucent">true</item>-->
    </style>
    
    <style name="AppTheme.NoBackground" parent="AppTheme">
        <!-- 布局渲染时, 不设置主题背景, 避免过度重绘 -->
        <item name="android:windowBackground">null</item>
    </style>

</resources>

在 AndroidManifest.xml 的 Activity 标签中设置该主题 , 即可取消该背景 ;

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="kim.hsl.rtmp">
    <application>
        <activity
            android:theme="@style/AppTheme.NoBackground"
            android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

或者在代码中设置主题 :

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        /*
            此时应用首界面启动完成, 将主题恢复成其它主题
            此处也可以根据不同的设置, 为应用设置不同的主题
         */
        setTheme(R.style.AppTheme.NoBackground);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
}

猜你喜欢

转载自blog.csdn.net/han1202012/article/details/106917546