一般人开篇都喜欢长篇大论,首先阐述一下android的渲染机制,再深入UI的绘制过程,最后以FPS漂亮收尾。我也看过形形色色的各类帖子和文章,说实话他们写的都比我好,所以我就不班门弄斧了,如果大家要看机制和原理,我推荐几个地址:
https://www.cnblogs.com/hanyonglu/p/4244035.html()
https://blog.csdn.net/a740169405/article/details/79037191
https://juejin.im/entry/5a5721d951882573291458ac
我现在要讲的是实操,在这里跟大家分享和讨论,
下面先看看优化效果。
登陆页面优化前: 登陆页面优化后:
很明显优化后比优化前:页面上的颜色浅了很多;页面下方的柱状图变少了,也变低了
那么大家可能就会好奇,我到底干了些什么?
我先提几个问题:
- 首先我们来了解一下用到到这个工具是什么?
答:这个工具说出来大家都不陌生,作为安卓开发,相信每个人都经常使用,它就是“开发人员选项”,看到 这里发现原来我们天天调试使用的一个工具里面就隐藏了一个监测过度渲染的功能。
- 然后我们来了解一下页面上到这个颜色代表的是什么?
工具开启位置:开发人员选项 -> 调试GPU过度绘制(Debug GPU overDraw)-> 显示过度绘制区域
- 原色:没有过度绘制
- 蓝色:1 次过度绘制
- 绿色:2 次过度绘制
- 粉色:3 次过度绘制
- 红色:4 次及以上过度绘制
- 最后我们来了解一下这个柱状图代表到是什么?
工具开启位置:开发人员选项 -> GPU呈现模式分析(Profile GPU Rendering)-> 在屏幕上显示为条形图
- 上图中的绿线:代表渲染时间在16ms以下,也是60fps的分界线。(在绿线以下的页面流畅无卡顿,在绿线 以上人眼能看到页面此时卡顿)
- 蓝色部分:代表测量绘制的时间。
- 红色部分:代表执行的时间。
- 橙色部分:表示的是处理时间
工具了解完了。现在进入主题,我们该怎么入手去进行优化?
- 第一步:安装你要检测过度绘制的应用。
- 第二步:按照上面B和C给出的路径打开我们要使用到的工具。
- 第三步:打开你要进行检测的页面。
这个时你见到就是图1-1的效果
那么这样的情况到底是不是过度渲染呢?有没有优化的空间?
在这里我选择了某Q来对比,
使用某Q重复以上三个步骤。效果见下图1-2:
我们的应用 某Q
图1-1 图1-2
通过两张图片的效果对比,你会发现某Q整个页面呈现蓝色,控件处呈现绿色;而我们的应用下半部分呈现蓝色,上半部分绿色,大部分控件处粉色,按钮处还呈现出红色。我们上面讲过
- 原色:没有过度绘制
- 蓝色:1 次过度绘制
- 绿色:2 次过度绘制
- 粉色:3 次过度绘制
- 红色:4 次及以上过度绘制
说到这里你是不是也发现问题了?没错某Q整个登陆界面大部分渲染次数控制在1次以内,只有少数绘制2次。我们的应用蓝,绿,粉,红都有。这就说明至少我们离某Q还有一定优化空间对吧。
分析:
1.同样是按钮“登陆”,“下一步”为什么某Q的颜色很浅,我们的很深?
仔细看某Q的其实不太像按钮有点像TextView,我们的用的是Button。
2.我们的渲染大部分都在绿线以上,某Q的基本都在绿线以下?
这个问题调试了很久,用排除法最终找到了原因,某Q进入登陆界面输入框没有获取焦点,而我们的应 用获取了焦点,区别就在这里。
见下图对比:
某Q没有获取焦点 某Q获取焦点后
然后我就去看代码,从代码入手解决问题。到底哪些代码会造成过度渲染?
去除无用background至少降低一层渲染:
去除无用嵌套降低若干层渲染:
使用TextView代替Button降低渲染层数至少3层渲染:
editText自动获取焦点改成手动点击后才获取焦点(光标造成的一直渲染问题)
我们来看看最终效果:
我们应用优化前 某Q登陆页面 我们应用优化后
是不是效果非常明显?把某Q放在中间,就是我们应用优化前和优化后的一个过度是吧。
首先颜色,从左往右3张图越来越浅
然后柱状图高度,从左往右3张图越来越矮
修改起来看上去不多,也很简单,小小的一些修改却花了我一个下午时间。由此引发的思考,细节往往决定成败,万丈高楼平地起,千里之堤溃于蚁穴。开发是一件非常严谨的事情,任何一行代码都不能马虎。
使用辩证思想去看待问题,用科学的方法去解决问题,往往能事半功倍:
- 提问
- 对比
- 分析
- 总结
哪些问题会造成过度渲染?以下都是在优化过程中总结出来的:
- UI层级过多
- 自定义View嵌套多,效率低等
- ListView没有复用
- 添加了过多的控件属性
- 在View层级相同的情况下面使用了绘制时间更长的布局。绘制时间比较:RelativeLayout > ConstraintLayout > LinearLayout > FrameLayout (常用布局比较)。
- 页面刷新太频繁
- 添加无关紧要的background(一个背景,绘制一次)
- 控件过多使用match_parent(能使用wrap_content尽量使用wrap_content,能限制控件大小尽量限制)
- 使用Button(使用TextView代替Button)
- 页面中有EditText的,自动获取焦点(非必要情况下面不要自动获取焦点,光标闪动会造成页面频繁的刷新)