关闭

RecyclerView局部刷新爬坑之路

标签: android
2644人阅读 评论(6) 收藏 举报
分类:

前几天看到的一篇文章,感觉和我的爬坑经历很像,感觉相见恨晚,所以转载一下。原文地址:安卓易学,爬坑不易—腾讯老司机的RecyclerView局部刷新爬坑之路

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

优化之前的效果:

这里写图片描述

优化之后的效果:

这里写图片描述

可以看到,优化之后,列表中的这张大图不在有一闪一闪亮晶晶的效果了! 那么,这是如何做到的呢?这是本文的重点,本文的大纲主要包括:

  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中去刷新你想更新的控件即可,并非是网上传闻的那些原因,当然此处爬坑时间之长,也可能更选用开源控件不当有关,所以,选择开源控件,要谨慎再谨慎!

4
0
查看评论

解决RecyclerView局部刷新时闪烁

RecyclerView局部刷新是由于其自带的item动画造成的,相信都看过RecyclerView在移除某个item时的删除动画吧,这个闪烁也是默认动画中的效果,所以只要去掉默认动画里的闪烁效果问题就解决了。代码如下:((DefaultItemAnimator) mRecyclerView.get...
  • CSDN_LQR
  • CSDN_LQR
  • 2017-01-04 19:42
  • 3501

腾讯老司机的RecyclerView局部刷新爬坑之路

作者:Hoolly,腾讯移动客户端开发工程师。商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处 WeTest导读安卓开发者都知道,RecyclerView比ListView要灵活的多,但不可否认的里面的坑也同样埋了不少人。下面让我们看看腾讯开发工程师用实例讲解自己踩坑时的解决方案和心路...
  • lf0814
  • lf0814
  • 2016-10-21 16:15
  • 2381

再说Android RecyclerView局部刷新那个坑

关键:public final void notifyItemChanged(int position, Object payload)RecyclerView局部刷新大家都遇到过,有时候还说会遇见图片闪烁的问题。优化之前的效果:优化之后的效果:如果想单独更新一个item,我们通常会这样做,代码如下...
  • jdsjlzx
  • jdsjlzx
  • 2016-10-22 17:06
  • 25016

RecyclerView使用之——数据刷新混乱及解决方案

初学Android,首次在项目中运用发生了RecyclerView刷新发生混乱的问题,困扰好久,终于解决,分享如下。 【问题现象】 项目中用RecyclerView做了一个医生排班列表,用于显示所有医生的排班信息,RecyclerView的一个项目(即一个医生),可以通过点前一周,下一周按钮查看...
  • feather_cool
  • feather_cool
  • 2018-01-03 15:09
  • 52

再说Android RecyclerView局部刷新那个坑——RecyclerView中payload参数实现刷新一个item的局部

转载自:http://blog.csdn.net/jdsjlzx/article/details/52893469 关键:public final void notifyItemChanged(int position, Object payload) RecyclerView局部刷新大家都遇...
  • qq_36523667
  • qq_36523667
  • 2017-12-06 16:31
  • 198

为 RecyclerView 增加监听以及数据混乱的小坑

为 RecyclerView增加监听 在实现好的MyAdapter中写内部接口:public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener) { this.onItemLongC...
  • hyson_yao
  • hyson_yao
  • 2017-01-18 01:17
  • 1050

RecyclerView 更新单个item时,闪烁问题的处理

情景描述1、调用mAdapter.notifyItemChanged(position);时,会重复加载图片,出现占位图等。 2、根据tag标记判断是否加载,不起作用。原因重复加载的原因就是onBindViewHolder的重复调用。而tag不起作用的原因则是每次更新都会使用一个新的holder。...
  • wove55678
  • wove55678
  • 2016-12-22 10:48
  • 1430

RecyclerView局部刷新的坑

话说有图有真相,首先来对比一下局部刷新前后的效果: 优化之前的效果: 优化之后的效果: 可以看到,优化之后,列表中的这张大图不在有一闪一闪亮晶晶的效果了! 那么,这是如何做到的呢?这是本文的重点,本文的大纲主要包括: 分析为什么会闪一下 对分析的可能造成闪动的问题进行解决 验...
  • professionIT
  • professionIT
  • 2016-10-21 18:51
  • 9529

使用原生自定义View,setState刷新界面后UI不能正常显示

背景项目整合react native时,将原生的一个九宫格图片显示,封装成了RN控件,并提供了一个source属性@ReactProp(name = "source")问题在js端使用该控件时,通过state初始化时给source赋值,然后,当添加图片是,通过setState刷新...
  • a631855639
  • a631855639
  • 2017-02-24 16:27
  • 2428

关于近期遇到的坑-SurfaceView,RecylerView等

近期参与了一个多人视频通话的业务,在其中使用SurfaceView负责显示用户的视频流,没想到被坑死。。 关于显示和隐藏背景: 由于是用六宫格的形式同时展示多人的视频,就选用了RecyclerView来实现,视频用SurfaceView展示,如果用户关掉了摄像头,使用语音模式就不显示SurfaceV...
  • qduningning
  • qduningning
  • 2016-11-10 14:25
  • 4157
    个人资料
    • 访问:216720次
    • 积分:3258
    • 等级:
    • 排名:第12376名
    • 原创:70篇
    • 转载:10篇
    • 译文:0篇
    • 评论:228条
    多多支持
    博客专栏
    最新评论