再说Android RecyclerView局部刷新那个坑

本文探讨了Android RecyclerView在局部刷新时出现图片闪烁的问题,分析了可能的原因,并介绍了如何通过使用`notifyItemChanged(int position, Object payload)`方法及payload参数避免全量更新,实现对特定控件的刷新,从而解决闪烁现象。同时提供了判断item是否在屏幕可见区域的代码示例,以及优化点赞和评论更新的方法。" 104163184,7484869,Ubuntu18.04搭建Hive3.1.2环境: JDK8 + SSH + Hadoop2.9.2,"['hadoop', 'hive', 'ssh', 'jdk', 'ubuntu']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                       

关键:public final void notifyItemChanged(int position, Object payload)

RecyclerView局部刷新大家都遇到过,有时候还说会遇见图片闪烁的问题。

优化之前的效果:

这里写图片描述

优化之后的效果:

这里写图片描述

如果想单独更新一个item,我们通常会这样做,代码如下:

mLRecyclerViewAdapter.notifyItemChanged(position);
  
  • 1

这里的position就是那个列表项的索引,调用这个方法可以更新一个Item的UI(当然,你要是直接调用notifyDataSetChanged()方法也可以,但这样会造成其他不需要更新的item也会刷新)。

即便如此,图片闪烁还是出现了,什么原因引起来的呢,这里猜测可以有如下几个原因:

  1. 流传甚为广泛的一种说法,imageView的宽高不固定导致的(wrap_content)?

  2. 是RecyclerView自带的更新动画效果导致的?

  3. 是因为图片加载框架(glide 的 animte)的动画效果导致的?

  4. getView中(RecyclerView中是onBindViewHolder)加载图片的时候,设置一个tag,当发现这个imageView的tag和之前的tag一致时就不加载。

这里我们不再对上面的原因进行具体的分析,针对上面可能引起闪烁的原因进行一一验证后的结果是令人感到失望的:都不是引起图片闪烁的根本原因。

那么怎么解决这个图片闪烁的问题呢?通过查看api,我们发现了另一个方法:

这里写图片描述

重点看payload参数介绍:

payload Optional parameter, use null to identify a "full" update
  
  • 1

翻译过来就是如果payload参数是null,那么就会来一个“完整的”更新,也就是说会全部更新。

我们再看一下mLRecyclerViewAdapter.notifyItemChanged(position)的源码:

这里写图片描述

从源码中看到,notifyItemChanged(position)调用了 notifyItemRangeChanged(int positionStart, int itemCount)方法,源码如下:

这里写图片描述

notifyItemRangeChanged(int positionStart, int itemCount)方法最终还是调用了notifyItemRangeChanged(int positionStart, int itemCount, Object payload)方法,只是payload参数是null。

那么如果payload传一个不为null的参数,就可以实现对列表项中的具体控件更新了吗?我们通过代码验证下。

模拟更新一条数据:

这里写图片描述

这里,我们将payload参数赋值为”jdsjlzx”,当然你也可以赋值为其他值,只要不空就行。

重写adapter中的onBindViewHolder(RecyclerView.ViewHolder holder, int position, List payloads)方法:

这里写图片描述

如果payloads列表不是空的,如上图所示,你就可以在else代码块里面刷新你想更新的控件了(记得不需要更新的控件就不要写在这里了)。

注意:

 

以上代码都是结合LRecyclerView框架来测试的,想要体验完整demo,请参考:https://github.com/jdsjlzx/LRecyclerView

总结

由此看来,RecyclerView做局部刷新还是非常容易的,其实就是使用好带payload参数的这个notifyItemChanged方法,以及重写带payload的这个onBindViewHolder方法,在onBindViewHolder中去刷新你想更新的控件即可。

PS:

拿朋友圈来说,我发一张照片,这就是一个item,但这个item里还要加上赞和评论。
当我有评论和赞要刷新时,我需要判断当前要改动的item是否是屏幕中的可见位置。如果是,通过调用带payload参数的这个notifyItemChanged方法更新item,就能达到只刷赞或者只刷评论,而不用重新加载照片(也就是图片闪烁的原因)的效果。

怎么判断当前position是位于屏幕中呢?下面给出参考代码:

private void doAnim(int position) {        int firstItemPosition = layoutManager.findFirstVisibleItemPosition();        if (position - firstItemPosition >= 0) {            //得到要更新的item的view            View view = mRecyclerView.getChildAt(position - firstItemPosition + 1);            if (null != mRecyclerView.getChildViewHolder(view)) {                ProductsViewHolder viewHolder = (ProductsViewHolder) mRecyclerView.getChildViewHolder(view);                //do something            }        }    }
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

上面代码同时也获取到了ViewHolder视图,有了ViewHolder,你还可以做其他操作哦(比如item动画效果)。

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值