文章来源:
http://wuxiaolong.me/2017/03/26/Rendering/
https://www.jianshu.com/p/989ce9eb7af8
hz:每秒刷新的次数
著名的“16ms”原则:
我们通常都会提到60fps(Frame Per Second)与16ms,可是知道为何会是以程序是否达到60fps来作为App性能的衡量标准吗?
60fps:人眼与大脑之间的协作无法感知超过60fps的画面更新。
*16ms:因为Android设定的刷新率是60fps,也就是每秒60帧,即16ms=1000/60Hz
Android系统每隔16ms会发出VSYNC信号重绘我们的界面。
就像这样:
image.png
如果你的某个操作花费时间是24ms,系统在得到VSYNC信号的时候就无法进行正常渲染,这样就发生了丢帧现象。那么用户在32ms内看到的会是同一帧画面。
image.png
Overdraw(过度绘制)是指系统在单个渲染帧中多次绘制屏幕上的像素。例如,如果我们有一堆堆叠的UI卡,不可见的UI也在做绘制的操作,这样会浪费大量的CPU和GPU资源。
渲染操作通常依赖于两个核心组件:CPU与GPU。CPU负责包括Measure,Layout,Record,Execute的计算操作,GPU负责Rasterization(栅格化)操作
如何检测?
-
Show GPU Overdraw
设置 -> 开发者选项 -> 调试GPU过度绘制 ->显示过度绘制区域。
对比一张Overdraw的参考图,分别有蓝色,淡绿,淡红,深红代表了4种不同程度的Overdraw情况:
image.png
蓝色,淡绿,淡红,深红代表了4种不同程度的Overdraw情况,我们的目标就是尽量减少红色Overdraw,看到更多的蓝色区域。
Overdraw有时候是因为你的UI布局存在大量重叠的部分,还有的时候是因为非必须的重叠背景。例如某个Activity有一个背景,然后里面的Layout又有自己的背景,同时子View又分别有自己的背景。仅仅是通过移除非必须的背景图片,这就能够减少大量的红色Overdraw区域,增加蓝色区域的占比。这一措施能够显著提升程序性能。
- Profile GPU Rendering
打开Profile GPU Rendering,显示每帧画面所需要渲染的时间。
设置 -> 开发者选项 -> GPU呈现模式分析 -> 在屏幕上显示为条形图
界面上会滚动显示垂直的柱状图来表示每帧画面所需要渲染的时间,柱状图越高表示花费的渲染时间越长。中间有一根绿色的横线,代表16ms,我们需要确保每一帧花费的总时间都低于这条横线,这样才能够避免出现卡顿的问题。
-
Hierarchy Viewer
用Hierarchy Viewer工具检查Activity中的布局是否过于复杂
Tools -> Android -> Android Device Monitor。
image.png
image.png
其实中带有红色或黄色的点代表速度较慢的View。
优化方案:
- 删除布局中不必要的背景属性
- 尽量减少布局的层级
来源:https://blog.csdn.net/xyz_lmn/article/details/14524567
减少视图层级<merge />
<merge/>标签在UI的结构优化中起着非常重要的作用,它可以删减多余的层级,优化UI。<merge/>多用于替换FrameLayout或者当一个布局包含另一个时,<merge/>标签消除视图层次结构中多余的视图组。例如你的主布局文件是垂直布局,引入了一个垂直布局的include,这是如果include布局使用的LinearLayout就没意义了,使用的话反而减慢你的UI表现。这时可以使用<merge/>标签优化。
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/add"/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/delete"/>
</merge>
现在,当你添加该布局文件时(使用<include />标签),系统忽略<merge />节点并且直接添加两个Button。
- 需要时使用<ViewStub />
<ViewStub />标签最大的优点是当你需要时才会加载,使用他并不会影响UI初始化时的性能。各种不常用的布局想进度条、显示错误消息等可以使用<ViewStub />标签,以减少内存使用量,加快渲染速度。<ViewStub />是一个不可见的,大小为0的View。<ViewStub />标签使用如下:
<ViewStub
android:id="@+id/stub_import"
android:inflatedId="@+id/panel_import"
android:layout="@layout/progress_overlay"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
当你想加载布局时,可以使用下面其中一种方法:
((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
// or
View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
当调用inflate()函数的时候,ViewStub被引用的资源替代,并且返回引用的view。 这样程序可以直接得到引用的view而不用再次调用函数findViewById()来查找了。
注:ViewStub目前有个缺陷就是还不支持 <merge /> 标签。
网友评论