这一次,我将卡顿彻底干掉了

做需求的过程中,不能死扣住一种实现方式,也许你发现你的优化之路已经到了尽头,但极有可能这只是一个开始

话说,我的app有着这样的一个页面:遇见未来的你。没错,它是我这个app的首页,所以,我无时无刻不在想着,怎么样保证这个页面,动画流程,滑动流畅,等等等等,总之,就是要保证流畅!

要了解这个页面为什么要优化,为什么做了一些优化,还先要说一下我们这个页面的业务:

以上是我们最初的想法,很显然,1秒钟就被否定了,uid集合也许很多,比如100多个,那么批量查询出的所有的用户这个数据量明显很大,存在两个很明显的弊端:

1、用户的流量极大浪费,后面88个我不care,你浪费我的流量,所以我卸载你的app。

2、失败率!没错,数据量大,一个显而易见的问题是接口失败率会有所上升。

3、且不说后台压力的问题。。

于是乎:

于是,前后台也达成了一致,因为以上问题都解决了,所以就这个方案了!

然而,身为前端的我缺遇到了一些其他的问题。

这个一个页面如何做,有没有原生的控件可以实现这样的效果,走出第一步尝试,我选择了ViewPager这条不归路,可以看到,like效果还是不错的。

爱情就像龙转风一阵。

 

然而,看下滑动卡片的效果,这个才是本文的重点:

可以看到,大部分时候滑动是不卡的,但是总有那么一个点(实际上是一段一段),是会卡一下的!因为时间的关系,之前的优化到了这里就告一段落,留下了一个小小的瑕疵。

那么,这是为什么?

这就要归功于我们的分批加载了,假如说,后台此次返回了100个uid,如果,前端每次加载20个,那么,需要5次才可以加载完,那么,首屏的加载实际上是在fragment(这个页放在fragment中)的onCreateView的时候就去加载,用户感知不到,或者说感觉不那么明显。

但是!

当到达第一分批加载的时候,也就是去拉取20-40条user信息的时候,就会卡你一下,那么为什么,因为你拿到数据塞给pagerAdapter之后,你需要调用一次notifyDataSetChange,如果你企图使用其他方式(反正我试过),那么,很抱歉,你将会遇到这位大爷:

java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged!

 那么,一定有人也不服气,比如说:这个卡顿也不一定是因为这个notifyDataSetChange带来的吧,会不会是UI有某些耗时的操作导致的呢?别急,我们问问traceView呗:

很抱歉,因为多次的优化,所以这里只能在第48位找到我们包名下面的一个耗时户,然而这里的inflate的内部的操作依然已经无法优化了,还记得上次,我们已经将占位资源全部都干掉了吗?然后,降低布局层级,只用一个RelativeLayout写出了这个布局,那么这里既然已经无法再做优化。

我们试试看看往上追踪,看谁调用了这个方法,能不能够有所突破,看看到底是不是notifyDataSetChange呢?

第一次:

。。。第N次:

然后,最后确认了,真的是notifyDataSetChange无疑,如果说不分批,即一次性加载,viewpager这个方案也就不不存在这个问题了。

那么,既然,我们找到元凶,那么该怎么办呢?

既然,是inflate操作这么耗时,而分批查询到数据添加到pagerAdapter中又不得不notifyDataSetChange一下,如果不做inflate操作,是否问题就解决了呢?

很容易,想到了RecyclerView,那么,何必不用RecyclerView去做一个类似的效果呢?

说干就干吧,花了一天的时间,重构这里的代码?

 private void addUserList(List<User> userList) {
        if (userList != null && userList.size() > 0) {
            int oldCount = mostMatchAdapter.getItemCount();
            mostMatchAdapter.addUserList(userList);
            int newCount = mostMatchAdapter.getItemCount();
            setAdapterState();
            mostMatchAdapter.notifyItemRangeInserted(oldCount, newCount);
        }

    }

最终,我们分批加载之后,不在是notifyDataSetChange了,而是现在的notifyItemRangeInserted。众所周知,RecycledViewPool lets you share Views between multiple RecyclerViews.因此,inflate耗时的问题,解决了。 

好吧,看看效果吧:

此时,依然是分批加载的背后,体现到前端的展示效果,缺已然没有了卡顿的存在。可以看到帧率大多在60以下,不在有很多尖锐的矩状出现了,滑动明显流畅了很多。

总结:在做需求的过程中,一开始难免会有方案的选择,当时的选择不一定是对的,当遇到问题提爬不过去了,是否考虑使用之前想到过的其他方案呢?

 


 

 

 

关于腾讯WeTest (wetest.qq.com)

 

腾讯WeTest是腾讯游戏官方推出的一站式游戏测试平台,用十年腾讯游戏测试经验帮助广大开发者对游戏开发全生命周期进行质量保障。腾讯WeTest提供:适配兼容测试;云端真机调试;安全测试;耗电量测试;服务器性能测试;舆情监控等服务。

 

最新文章
1WeTest携PC&主机游戏质量保障服务和性能测试平台PerfDog亮相Gamescom 2024 以全场景游戏质量保障服务及性能测试解决方案,助力全球游戏行业的创新与发展
2一张图带你了解小程序隐私合规检测 快速了解小程序隐私合规检测如何防范黑灰产风险,守护用户数据安全
3防范小程序隐私合规风险,筑牢用户信任防线 了解隐私合规检测如何帮助小程序规避数据安全风险
4WeTest 海外测试需求有奖问卷活动中奖名单公布 近日,WeTest 海外测试需求有奖问卷活动圆满结束,经过紧张的统计与筛选,以下朋友们中奖,成功获得了我们的门票礼品。
5海外本地化测试的全生命周期服务 第三期 支付测试 海外支付风控升级,非本地测试封号现象频发,真金测试推进困难?来看WeTest的本地化支付测试方案
购买
客服
反馈