提要:
- 以下仅为个人查阅资料,视频总结所得,如有错误,请指出谢谢
优化要点:
- 本文优化是针对启动时App的界面渲染进行优化,主要体现在XML优化
知识储备:
- 我们需要了解CPU和GPU的工作流程
- 卡顿原理
CPU和GPU:
-
CPU的任务繁多,除了进行逻辑计算外,还要进行内存管理,显示操作,因此在实际运算的时候新能会大打折扣,在没有GPU的时代,不能显示复杂的图形,其运算速度远跟不上今天复杂三维游戏的要求。这时 GPU的设计就出来了
CPU和GPU比较
- 区别:
总的来说,CPU和GPU的主要区别是CPU是通用计算,而GPU是专用计算。打个比方来讲,CPU是老教授,能力很强但数量很少,GPU是小学生,能力很弱但数量众多。GPU的高性能主要体现在并发性上。现在虽然CPU也是多核,但是CPU的并发就像是10个人每个人处理一个问题,而GPU的并发是1个人处理10个问题,两者在效率上具有很大的差异。所以计算密集型的程序和易于并行的程序更适合在GPU上运行。
绘制流程:

- 我的理解是: 我们在XML中的打代码通过LayoutInflater 生成Button对象,对象在经过CUP生成多维图形纹理,生成后的数据在通过GPU栅格化后绘制出Button的样式
整个流程主要是体现在View的onMeasure(),onLayout(),onDraw()三个方法上面
卡顿的原理
60Hz刷新频率由来
12 fps: 由于人眼睛的特使结果,在画面高于10-12帧/秒播放时,人会认为画面是连贯的
24 fps :有声电影的拍摄及播放帧率均为每秒 24 帧,对一般人而言已算可接受
30fps:早期的高动态电子游戏,帧率少于每秒 30 帧的话就会显得不连贯,这是因为没有动态模
糊使流畅度降低
60 fps:在与手机交互过程中,如触摸和反馈 60 帧以下人是能感觉出来的。 60 帧以上不能察觉变化当帧率低于 60 fps 时感觉的画面的卡顿和迟滞现象
Android 系统每隔 16ms 发出 VSYNC 信号 (1000ms/60=16.66ms) ,触发对 UI 进行渲染, 如果每次渲染都成功这样就能够达到流畅的画面所需要的 60fps,为了能够实现 60fps ,这意味着计算渲染的大多数操作都必须
在 16ms 内完成。
原理分析:
而每一帧的渲染包括CPU的一次计算,GPU的一次绘制,当一帧画面出现渲染时间超过16ms的时候,垂直同步机制会让显示器硬件等待GPU栅格化渲染操作,造成这一帧的渲染进入本应是下一帧的渲染时间段,这样会造成这一帧的画面多停留了16ms,甚至更多,这样就会造成了用户开起来界面停顿现象。

处理方案:
方法一:
- 打开手机开发人选选项中的调适GPU过度绘制选项,选中显示过度绘制区域
-
打开APP
APP过度绘制示意图
说明:

- 通过两幅图可以明显看出文本内容区域过度绘制了4次及以上
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:paddingBottom="@dimen/chat_padding_bottom">
<ImageView
android:id="@+id/chat_author_avatar"
android:layout_width="@dimen/avatar_dimen"
android:layout_height="@dimen/avatar_dimen"
android:layout_margin="@dimen/avatar_layout_margin" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:orientation="vertical">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#fff"
android:textColor="#78A">
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/chat_author_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:gravity="bottom"
android:padding="@dimen/narrow_space" />
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/chat_datetime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:padding="@dimen/narrow_space"
android:textStyle="italic" />
</RelativeLayout>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/chat_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/narrow_space"
android:background="#fff"/>
</LinearLayout>
</LinearLayout>
-
通过代码可以看出外层RelativeLayout设置背景为白色,与外层LinearLayout的背景设置发生重复绘制,我们将RelativeLayout的背景设置去掉,结果如下:
取消RelativeLayout背景设置
方法二:
- 在开发中我们还会遇到这样的问题:


在渲染视图中我们发现在三张图片的重叠部分发生了过度绘制,我们需要对重叠部分进行优化:

B图片也覆盖了A图片部分,上图未标出

另外:
- include标签:除了减少GPU绘制方法外,我们还可以在APP重复使用的相同控件处使用include标签进行引入,减少CPU的计算,在后面使用的时候可以直接进行绘制
- merger标签:减少与父容器的重叠
- 减少布局的嵌套:在XML文件中减少布局的嵌套也可以减短XML的绘制时间,推荐使用ConstraintLayout,RelativeLayout布局。
结束
感谢您的阅读,希望上面的内容对您有所帮助
生命不止,学习不止,与君共勉
网友评论