Android应用怎样才能如丝般顺滑

  • 2019 年 10 月 28 日
  • 笔记

背景

现在医美行业竞争激烈,产品打入市场直接可获客的就是用户的体验度,这个体验度除了有完善的功能外,更重要的还有界面UI的操作流畅度,流畅度的好坏,对一个产品的体验和口碑有着极大的影响,当年Android 手机经常被人诟病的一点就是流畅度远远比不上iPhone,即使到现在,这个影响也依然存在。

为了提高流畅度,其实Google对android系统也进行了大量的优化:

1、使用GPU进行硬件加速;

2、引入VSync机制;

3、把Dalvik换成art;

…….

流畅度评测指标FPS—>SM

对于流畅度的评测,大家第一时间会想到FPS。当前业界衡量一个APP是否流畅的主要指标就是FPS。但是有经验的同学会发现使用FPS测试APP的流畅度,会存在测试数据和实际感官不一致的问题,比如有时候FPS很低,但是APP看起来确实很流畅。

举个例子:

操作淘宝APP的首页,进行页面的滑动,实际感官很顺畅。让我们来看看FPS的值吧。

从图表中的数据我们可以看到:

1)为什么FPS很低,但是我们不觉得APP卡顿?

2)APP停止操作之后,FPS还是一直在变化,这样的情况是否会影响到FPS的准确度?

出现这种现象原因是什么呢?基于这两个问题 我们分析一下FPS的原理:

FPS的原理:

1、手机屏幕显示的内容是通过Android系统的SurfaceFLinger类,把当前系统里所有进程需要显示的信息合成一帧,然后提交到屏幕进行显示。

2、1s内SurfaceFLinger提交到屏幕的帧数。

根据这个原理就可以解释上面的问题了:

1)如果APP在1S内只有30帧的显示需求,比如画一个动画只画了0.5s就画完了,那么FPS最高也就只有30帧/秒,并不能代表APP是卡顿的。另外如果屏幕根本没有绘制需求,画面是静止的,那FPS就是0。

2)屏幕上显示的每一帧合成都是针对手机里的所有进程的,所以即使APP停止了绘制,手机里其他的进程可能还在绘制。

通过上面的分析我们得出:FPS来作为流畅度的指标是不准确的,那流畅度的指标用什么来描述更为准确呢?别急,鹅厂自主研发的性能工具–GT可以帮助我们准确的检测一个APP的流畅度。

小贴士

GT(随身调)是APP的随身调测平台,它是直接运行在手机上的“集成调测环境”(IDTE, Integrated Debug Environment)。利用GT,仅凭一部手机,无需连接电脑,您即可对APP进行快速的性能测试(CPU、内存、流量、电量、帧率/流畅度等等)、开发日志的查看、Crash日志查看、网络数据包的抓取、APP内部参数的调试、真机代码耗时统计等。

GT工具中的SM(SMoothness)指标给出来一个衡量流畅度好坏的标准,如下图:

可能有人会有疑问:如果出现了SM值<=50的情况,我们要怎么办呢?或者我们拿这个SM的值去衡量一个APP的流畅度,开发同事是否认可呢?这个时候我们就看用他们经常会用到的工具和方法来验证SM检测的结果是否正确。

下面会从两个维度去介绍影响流畅度的因素和相应的检测工具。

从UI层优化入手

GPU 过度绘制+Trace for OpenGL

过度绘制:在屏幕一个像素上绘制多次,比如一个TextView后有背景,那么显示文本的像素至少绘制两次,一次是背景,一次是文本。

小贴士

如何实现过度绘制:打开安卓手机,找到设置—》开发者选项—》调试GPU过度绘制打开。

古语有云:知己知彼,方能百战百胜,我们想要比别人做的好,就要先了解一下自己和别人的差距,下面我们就比较一下淘宝、竞品(更美,医美分期的APP)还有么么钱包这三款APP 的过度绘制的情况。

淘宝 更美 么么钱包

从上面三个图中可以看出界面上会出现各种颜色,颜色和过度绘制有什么关联呢? 可以看下下面的表格:

通过对比我们发现:

? 淘宝的首页和颜色基本上蓝绿色居多,过度绘制正常。

? 么么钱包的首页基本上是绿色和浅红色,过度绘制有待检查。

? 更美的首页颜色分布大部分是偏向暗红,过度绘制需检查。

下面我们就以么么钱包【我的】页面,来检查下过度绘制:

我们看看是否可以优化,这些区域是怎么形成的呢? 我们可以借助于工具进行记录和分析APP每一帧的绘制过程。

首先连接设备,然后打Android-sdk/tools/monitor.bat

1、点击V字型的按钮,会有个弹框:

2、填写对应应用的信息

Device:连接的设备名称

Application Package:应用对应的包名

Activity to launch:填写应用对应的Main Activity

Destionation File:trace 保存的路径

3、点击【Trace】然后进入录制页面,此时打开APP到要检查的页面

点击【Stop Tracing】

然后就可以通过trace文件进行分析:

通过演示我们发现:

? 列表部分【我的订单】,两次绘制之后没有变化(按照正常情况,每绘制一次,都会有新增新绘制的UI)。

? 最后呈现的列表中的元素是在第一层刷完的上面进行叠加的。

对于上面发现的问题,给出初步的解决建议:

? 去掉多余的绘制。

? 第一次绘制的时候,是否可以根据尺寸 提前设计好上半部分和小半部分背景颜色的设置(如:上面是黑灰色,下半部分是灰白色)

最后,把分析的结果提供给开发 优化的时候做下参考。

小贴士

并不是所有的有红色部分就一定要修改的,这要根据UI情况而定,有些UI设计的比较复杂,红色区域可能会多一点。

UI布局不合理+Hierarchy Viewer

UI的布局会影响到一个APP的视觉体验,好的布局方式,往往能带来舒服的视觉效果,更能得到用户的接受与好评。

UI的布局可以通过Hierarchy Viewer这个工具来分析,主要分三种类型:

? 没有用的父布局。是指没有背景绘制或者没有大小限制的父布局,这样的父布局不会对UI效果产生任何影响,没有用的父布局可以通过</merge>标签合并来减少UI层次。

? 使用线性布局(LinearLayout)排版导致UI层次变深。如果遇到这种问题可以使用相对布局RelativeLayout代替LinearLayout,减少UI的层次。

? 不常用的UI被设置成了GONE,比如error页面,请求网络前不需要显示的页面。

下面来看看我们的么么钱包页面的UI布局是怎样的?

1. 首选 打开Android-sdk/tools/hierarchyviewer.bat

2. 选择模拟器或者真机,找到对应的APP 的包名/MainActivity

3.点击【Load View Hierarchy】

点击后,UI布局如下图:

根据上面介绍的三种类型,可以看到:

1、多处用到了线性布局,是否可以用RelativeLayout布局代替。

2、RelativeLayout从父布局到子布局没有任何背景绘制,是否是没有用的父布局。

把发现的问题可以反馈给开发,看看是否布局方式可以优化,图中的标注已经和开发确认可优化。

从代码层入手

Lint 扫描,发现代码中的流畅度问题

Lint 扫描通过静态扫描检查代码的方式,能够发现在代码中潜在的问题,并给出问题的原因和在代码中的位置,并给出相应的优化建议。

如何进行Lint扫描呢?

首先 从GIT上下载APP的源码,用AndroidStudio打开工程,选择Analyze下的Inspect Code,会出现如下弹框:

根据检查的范围 自行选择,然后点击【OK】键,出现如下 等待检测的进度框:

检测完后就会展示检测结果。

下面是抽取钱包部分代码进行检查,检查结果如下:

我们从检查结果可知,Lint扫描后会给出所有在这个项目中不规范的编码、多余的资源、可能的BUG、或者其它的一些问题,然后会给出相应的修改建议供我们参考,虽然有些问题并不会影响APP的正常运行,不过这对于项目的规范性和维护性来说是非常重要的。

Traceview,寻找卡主主线程的地方

我们在测试APP的时候,有时候会发现程序在运行一段时间后发现发烫、卡顿的现象,这时候我们可以借助Traceview 工具进行分析。

Traceview 主要是找出主线程耗时较大的函数,减少调用。主要方式有以下两种:

? 找出在主线程耗时较大的函数,看看能否通过优化逻辑去减少API的耗时。

? 分析滑动过程中CPU的工作,看看能否让CPU优先执行主线程的工作,尽量不要被其他线程抢占。

分析面板中各个指标的含义:

连接设备(模拟机或者真机),然后打开Android-sdk/tools/ddms.bat,选择对应的应用

点击上方的红色带点按钮,红色点会变成了灰色方块,结束录制后,再次点击这个按钮,就会弹出如下所示的分析数据图:

由于本文讨论的是和APP流畅度相关的,所以我们主要看两个值 Cpu Time/Call和Call+Recur Calls/Total (单位是毫秒), 从Profile Pane 中可以看出 Cpu Time/Call和Call+Recur Calls/Total值都不大,在滑动过程中cpu占用的时间分配比较合理,基本上都是主线程用。

那是不是这两个值要是高就一定有问题呢?答案是不一定的,这要根据实际的业务场景来决定,从之前我的测试经验看,分析这两个值高大致的原因基本上就是:

1、业务逻辑复杂,主线程要处理的业务请求量多 CpuTime和Call+Recur Calls/Total占用时间过长。

2、一个方法处理任务比较重,CpuTime和Call+Recur Calls/Total 占用时间较长。

有时候我们测出来值偏高,但是不知道是不是代码缺陷,这个时候我们测试可以提出一些疑问,把具体的父类调用的具体方法提供给开发,让开发配合查下代码,看看是不是可以优化。如果真的是代码问题占用时间过长,可以建议开发放到异步线程内处理。

总结

卡顿(ANR)问题的严重性,可能不像崩溃(Crash)来得那么强烈,但对于用户的流失影响是潜移默化,慢慢深入。我们在测试的时候,可以用上面讲到的一些方法和工具处理并修复应用中的流畅度问题,确保我们提供的应用程序能够给用户提供优良的渲染性能,实现了平滑流畅的60FPS。

李敏

享米测试工程师