关键:public final void notifyItemChanged(int position, Object payload)git
RecyclerView局部刷新你们都遇到过,有时候还说会碰见图片闪烁的问题。github
优化以前的效果:api
优化以后的效果:框架
若是想单独更新一个item,咱们一般会这样作,代码以下:ide
mLRecyclerViewAdapter.notifyItemChanged(position);
这里的position就是那个列表项的索引,调用这个方法能够更新一个Item的UI(固然,你要是直接调用notifyDataSetChanged()方法也能够,但这样会形成其余不须要更新的item也会刷新)。测试
即使如此,图片闪烁仍是出现了,什么缘由引发来的呢,这里猜想能够有以下几个缘由:优化
流传甚为普遍的一种说法,imageView的宽高不固定致使的(wrap_content)?动画
是RecyclerView自带的更新动画效果致使的?spa
是由于图片加载框架(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 >= 0) { //获得要更新的item的view View view = mRecyclerView.getChildAt(position - firstItemPosition + 1); if (null != mRecyclerView.getChildViewHolder(view)) { ProductsViewHolder viewHolder = (ProductsViewHolder) mRecyclerView.getChildViewHolder(view); //do something } } }
上面代码同时也获取到了ViewHolder视图,有了ViewHolder,你还能够作其余操做哦(好比item动画效果)。