Android RecyclerView局部刷新那个坑
关键:public final void notifyItemChanged(int position, Object payload)
RecyclerView局部刷新大家都遇到过,有时候还说会遇见图片闪烁的问题。
优化之前的效果:
优化之后的效果:
如果想单独更新一个item,我们通常会这样做,代码如下:
mLRecyclerViewAdapter.notifyItemChanged(position);
这里的position就是那个列表项的索引,调用这个方法可以更新一个Item的UI(当然,你要是直接调用notifyDataSetChanged()方法也可以,但这样会造成其他不需要更新的item也会刷新)。
即便如此,图片闪烁还是出现了,什么原因引起来的呢,这里猜测可以有如下几个原因:
流传甚为广泛的一种说法,imageView的宽高不固定导致的(wrap_content)?
是RecyclerView自带的更新动画效果导致的?
是因为图片加载框架(glide 的 animte)的动画效果导致的?
getView中(RecyclerView中是onBindViewHolder)加载图片的时候,设置一个tag,当发现这个imageView的tag和之前的tag一致时就不加载。
这里我们不再对上面的原因进行具体的分析,针对上面可能引起闪烁的原因进行一一验证后的结果是令人感到失望的:都不是引起图片闪烁的根本原因。
那么怎么解决这个图片闪烁的问题呢?通过查看api,我们发现了另一个方法:
重点看payload参数介绍:
payload Optional parameter, use null to identify a "full" update
翻译过来就是如果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 >= ) {
//得到要更新的item的view
View view = mRecyclerView.getChildAt(position - firstItemPosition + );
if (null != mRecyclerView.getChildViewHolder(view)) {
ProductsViewHolder viewHolder = (ProductsViewHolder) mRecyclerView.getChildViewHolder(view);
//do something
}
}
}
上面代码同时也获取到了ViewHolder视图,有了ViewHolder,你还可以做其他操作哦(比如item动画效果)。
Android RecyclerView局部刷新那个坑的更多相关文章
- 再说Android RecyclerView局部刷新那个坑
RecyclerView局部刷新大家都遇到过,有时候还说会遇见图片闪烁的问题. 优化之前的效果: 优化之后的效果: 如果想单独更新一个item,我们通常会这样做,代码如下: mLRecyclerV ...
- 安卓易学,爬坑不易—腾讯老司机的RecyclerView局部刷新爬坑之路
前言 安卓开发者都知道,RecyclerView比ListView要灵活的多,但不可否认的里面的坑也同样埋了不少人.下面让我们看看腾讯开发工程师用实例讲解自己踩坑时的解决方案和心路历程. 话说有图有真 ...
- 安卓易学,爬坑不易——腾讯老司机的RecyclerView局部刷新爬坑之路
针对手游的性能优化,腾讯WeTest平台的Cube工具提供了基本所有相关指标的检测,为手游进行最高效和准确的测试服务,不断改善玩家的体验.目前功能还在免费开放中. 点击地址:http://wetest ...
- RecyclerView局部刷新那点事
1.局部刷新的引入 提到RecyclerView,我们首先想到的是ListView,对于ListView的局部刷新,我们之前已经有解决方案,[android:ListView的局部刷新]当时的解决方案 ...
- Android listview局部刷新和模拟应用下载(zhu)
在android开发中,listview是比较常用的一个组件,在listview的数据需要更新的时候,一般会用notifyDataSetChanged()这个函数,但是它会更新listview中所有可 ...
- 转:android listview局部刷新和模拟应用下载
在 android开发中,listview是比较常用的一个组件,在listview的数据需要更新的时候,一般会用 notifyDataSetChanged()这个函数,但是它会更新listview中所 ...
- RecyclerView 局部刷新(获取viewHolder 去刷新)
RecyclerView.ViewHolder viewHolder = mRecyclerView.findViewHolderForAdapterPosition(i); if (viewHold ...
- RecyclerView 数据刷新的几种方式 局部刷新 notify MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- android:ListView的局部刷新
1.简介 对于android中的ListView刷新机制,大多数的程序员都是很熟悉的,修改或者添加adapter中的数据源之后,然后调用notifyDataSetChanged()刷新ListView ...
随机推荐
- sata express接口
华硕z97主板的sata express接口目前没什么用,但随着电脑接口的发展,可能会占据一席之地. 1.顾名思义,SATA-Express是SATA接口 + PCI-Express的混合体,其理论带 ...
- Eclipse配色方案插件 真漂亮!
原文:https://my.oschina.net/jean/blog/208263 最近发现了一个Eclipse配色方案插件,这回给Eclipse配色太方便了. 插件主页:http://eclips ...
- centos7grub2 引导win10
centos7+win10安装完成之后,使用gurb2引导win10系统 方式:使用ntfs-3g 步骤: 1.加源 wget -O /etc/yum.repos.d/epel.repo http: ...
- phpunit 单元测试框架-代码覆盖率
"phpize not found" 的解决办法: apt-get install php5-dev http://jeffreysambells.com/2010/04/08/r ...
- Scala-LIST/Tuple/Map
环境: CentOS 6.3 LIST(列表) 代码: $ cat list.scala var mylist = List(1,2,3) println(mylist) var mylist1 = ...
- HDU - 3584 Cube (三维树状数组 + 区间改动 + 单点求值)
HDU - 3584 Cube Time Limit: 1000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u Subm ...
- yarn-cli 简介
Yarn 提供了丰富的命令行命令来帮你应付你所开发的 Yarn 包的方方面面的工作,包括安装.管理.发布等等. 虽然我们在这里按照字母顺序列出了我们提供的所有命令,但是某些更常用的命令还是要着重提一下 ...
- 基于Canvas的Char.js库使用
Chart.js是基于Html5 Canvas的图表库. 官网:http://www.chartjs.org/ 參考文档:http://www.chartjs.org/docs/ 支持六种图表,相应源 ...
- OSX:不同OSX版本号的标记可能不兼容
现象: 依据測试,中文OS X 10.9和中文10.10的文件标记彼此不兼容. 也就是说.比方在10.9中的颜色标记,在10.10DP2中不能删除,但能够加入/删除10.10自己的颜色标记,反之亦然. ...
- iOS方法重写
在O-C中子类可以继承父类的方法 ,而不需要从新编写相同的方法,但是有有时候子类并不想原封不动的继承父类的方法,而且是想做一些修改,这就采用啦方法的重写,方法从写有叫做方法覆盖,若子类的中的方法与父类 ...