安卓易学,爬坑不易——腾讯老司机的RecyclerView局部刷新爬坑之路

作者:Hoolly,腾讯移动客户端开发工程师。

商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处。

WeTest导读

安卓开发者都知道,RecyclerView比ListView要灵活的多,但不可否认的里面的坑也同样埋了不少人。下面让我们看看腾讯开发工程师用实例讲解自己踩坑时的解决方案和心路历程。

话说有图有真相,首先来对比一下局部刷新前后的效果:

优化之前的效果:

优化之后的效果:

可以看到,优化之后,列表中的这张大图不在有一闪一闪亮晶晶的效果了!

那么,这是如何做到的呢?这是本文的重点,本文的大纲主要包括:

  1. 分析为什么会闪一下
  2. 对分析的可能造成闪动的问题进行解决
  3. 验证是否解决

一、为什么会闪一下?

我们的需求是大家已经看到了,点击打分,弹出一个对话框,点击一个分数,这时候,通过一些列复杂的转换(当然不是本文的论述的重点),这时候到了要更新列表项了,如是很自然,我们会这么做:

因为,操作的那个列表项你是知道他的position,所以你可以这么做,(当然,我之前是直接notifyDataSetChanged的,这个会照成所以不不要的item也会刷新)然而,闪动还是出现了,那么我开始怀疑:

  1. 流传甚为广泛的一种说法,imageView的宽高不固定导致的(wrap_content)?
  2. 这个是RecyclerView自带的更新动画效果导致的?
  3. 这个是因为图片加载框架(glide 的 animte)的动画效果导致的?
  4. getView中(RecyclerView中是onBindViewHolder)加载图片的时候,设置一个tag,当发现这个imageView的tag和之前的tag一致时就不加载

二、带着思考,就去尝试吧!

1、对于第一种,我的做法是自己写了一个自定义的imageView,重写omMeasure方法,如下:

因为我们的这个列表项中的图片是(高=宽)的,因此,我才这么写,这样写也有一个好处,不用在onBindViewHolder中去动态的计算出高度,然后在已layoutParm的方式设置给imageView,相信不少小伙伴都做过了吧!

然而,遗憾的是,他并没有解决闪一下的问题!此时这个闪动的原因显然不在这里,但是这里做的,可以保留下来。

2、对于第二种说法,我参考了这里

http://stackoverflow.com/questions/29331075/recyclerview-blinking-after-notifydatasetchanged

的做法:

以及也尝试了这种

然而,那种渐变的闪动消失了,但是,取而代之的是一种更加不可接受的闪动,这里就不用gif展示了,因此原因也并不在此处。

3、对于对三种说法,我也去尝试了一下将glide加载改为:

然而得到的依然是一个失望的结果,依然没有解决闪动的问题,原因也不在此处。

4、那么,就剩下最后一个猜测了,那么会不会是它呢?那就试试吧,于是代码改为:

这里的做法其实就是设置Tag,那么是骡子是马,拉出来溜溜吧,结果更加令人发指,如图:

好吧,此时已经有点崩溃了,显然这个也不是我要的结果,那么此时是否应该在静下来想一想,自己对于可能的几种原因做过的一些对策,是否有哪里遗漏了。经过思考,发现并没有!!那么一定是还有其他的原因,没有考虑到!

还是去翻一翻RecyclerView的api吧,我注意到了这个api:

可以看到这里有一个payload的参数,use null to identify a "full" update这是说如果传null就是全部更新,回过头去看一看我们之前的调用方式:

看一下源码,发现

实际上,payload这个参数就是传的null,那也就是说如果传一个不为null的参数,就可以对列表项中的具体控件更新了?

http://stackoverflow.com/questions/33176336/need-an-example-about-recyclerview-adapter-notifyitemchangedint-position-objec

我了解到这个方法的使用方式是这样的:

然来,onBindViewHolder有这么一个重载方式,如是我也这么做了,在下面这个重载中,去更新我想更新的控件:

然后,更新的方式变成了这种:

是骡子是马,那就在遛一遛吧!

然而,依然是会闪一下!!!这这么会!!!还是调试一下吧,新重载onBindViewHolder方法有没有被执行,一更代码,发现果然没有被执行!

那么,究竟是什么鬼?去网上查了一下,有人给出了一个解决办法:

http://stackoverflow.com/questions/32463136/recyclerview-adapter-notifyitemchanged-never-passes-payload-to-onbindviewholde

需要重写这个动画,让永远返回true,已达到newHolder和olderHolder是同一个,然而,这真的就是我的救命稻草吗?

那么,是骡子是马,拉出来溜溜吧,然而,并不是马!!进源码看一看

发现其实只要我们传入的payload不为空,那么返回的就是true?重写有意义吗?显然,我重载的onBindViewHolder方法并没有执行的原因显然不是这个。

那么,到底,到底问题出在何处?会不会是XrecyclerView的问题?根据调用栈,我看到第一个onBindViewHolder被执行了,往上面跟,发现XrecyclerView的实现果然存在问题!

如图,作者仅仅只实现了,不带payload的方法,最后adapter调用的只有不带paylaod的方法!所以,重写一个吧!

最后!终于达到了想要的效果了,经过这次爬坑,选择一个开源的框架真滴是需要慎重再慎重。

总结

实际上RecyclerView做局部刷新是非常容易的,其实就是使用好带payload参数的这个notifyItemRangeChanged方法,以及override带payload的这个onBindViewHolder方法,在onBindViewHolder中去刷新你想更新的控件即可,并非是网上传闻的那些原因,当然此处爬坑时间之长,也可能更选用开源控件不当有关,所以,选择开源控件,要谨慎再谨慎!

关于腾讯WeTest

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

原文发布于微信公众号 - 腾讯WeTest(TencentWeTest)

原文发表时间:2016-10-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏.NET技术

MVC系列之开始

   4月5号晚本来应该写出来的,这几天迷上了炉石传说,打得有点疯,明天又得上班了,收拾心情还是得写出来。上星期5晚上回家的时候,不得不吐槽一下的确有点背。6点...

1002
来自专栏全华班

轻量级项目任务管理系统

--------------------------------------------------

6714
来自专栏ThoughtWorks

在前端性能优化中应用HTTP缓存的三部曲|洞见

Spike先生是Best Experience公司的IT运营部门主管,他的团队成功地利用Http Cache优化了前端工程。 Spike将通过三个Scenari...

3214
来自专栏阮一峰的网络日志

Google短网址的API

除了速度快,goo.gl还提供详细的点击统计。比如,Yahoo首页的短网址是http://goo.gl/QuXj,那么它的统计数据就在http://goo.gl...

9112
来自专栏逸鹏说道

一个粗心的Bug,JSON格式不规范导致AJAX错误

一、事件回放 今天工作时碰到了一个奇怪的问题,这个问题很早很早以前也碰到过,不过没想到过这么久了竟然又栽在这里。 当时正在联调一个项目,由于后端没有提供数据...

3564
来自专栏DeveWork

WebFont 三宗罪之一:WebFont 与 FOUT

四赴T.I.T 创意园面试,所学甚多。这篇文章是昨天面试中探讨的一个问题所延伸而来,现在都说WebFont 怎么好怎么好,让我们逆向思维,揭底WebFont 的...

2997
来自专栏木头编程 - moTzxx

微信公众平台开发[6] —— 微信开发集成类的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011415782/article/de...

1823
来自专栏一个番茄说

iOS 开发安全那些事儿

​ 随着移动互联网的普及,被越来越多的心怀不轨的人觊觎,也越来越多的安全问题暴露了出来。开发者开发出来的应用被安装在设备上之后,用户并不具有专业的安全知识。...

1013
来自专栏不二小段

【一起学Python】STEAM游戏评测爬虫

别催更,越催越懒得写。催更只接受赞赏…可惜我的微信还没有赞赏的功能… 今天刚接的需求&新鲜的代码… 有个大佬昨天跟我说 来给我爬一下Steam的游戏评测吧,我...

1.2K6
来自专栏用户2442861的专栏

必不可少的Firefox插件

Adblock Plus 去广告,包括youku的开头广告 All-in-One Sidebar 最大的好处就是省去书签栏 NoSquint :用firefo...

4031

扫码关注云+社区

领取腾讯云代金券