RecycleView 在调用Adapter.notifyDataSetChanged()的时候往往整个屏幕会闪烁,特别是有Picasso这种异步加载图片框架的时候特别明显。这里有几种方法可以解决,个人比较推荐第三种方式:通过更改ViewHolder 来更新,虽然感觉上会麻烦些,但是体验效果特别特别好!
1.只更新1个item:
Adapter有许多更新方式 除了notifyDataSetChange还有很多,有时间大家可以看看,我们这里直接调用
Adapter.notifyItemChanged(int Position),
这种方式可以只刷新你要更新的数据,其他的数据是不会更新的,其他的也就不闪了。
2.取消动画
上述第一个方法有个弊端,就是你要更新的那个item会有刷新闪烁,其实我也看了一些人的资料,然后去项目里面看源码,RecycleView用的动画实体类是DefaultItemAnimator 这个类继承的父类是SimpleItemAnimator,然后这个类的父类是在RecycleView里面的抽象类ItemAnimator,其中定义如下:
private long mAddDuration = 120;
private long mRemoveDuration = 120;
private long mMoveDuration = 250;
private long mChangeDuration = 250;
看到了吧,动画也是要有执行时间的,总结来说就是更改recycleView的动画,减少动画时间可以减少item的闪烁。
设置动画大致方法:
recyclerView.getItemAnimator().setChangeDuration(0); //设置更新动画duration为0,其他的你也可以设置。
((DefaultItemAnimator)mRecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);//取消动画
或者你愿意的话自定义一个动画类,这个类必须继承自SimpleAnimator,换个说法就是,改一下DefalutAnimator 中的动画效果
因为RecycleView 的动画实体类就是它。不讲太细,我们的目标是页面不闪烁。
3.通过更改ViewHolder 来更新
我觉得更新数据是最轻松的,通过下面那个方法获取ViewHolder,有了viewHolder,有了数据你啥不能更新的, 想更新什么就更新什么,而且可以避免因为重新OnBinderView 导致的资源浪费。使用这个的时候同时要记得更新adapter 中的数据集,避免数据不一致。
(myAdapter.CustomViewHolder) mRecyclerView.findViewHolderForAdapterPosition(i);//获取ViewHolder
这好归好,但是这里往往有些问题,一般adapter 里面的ViewHolder 很少拿到 adapter 外部去,都是在Adapter里面更新,这样ViewHolder 的内容可以随便变化,只要数据是对的就好了,但是拿到外部去了之后,以后你想改代码要麻烦死了虽然我是这样解决的
mAdapter.updateView(holder,n);
但是也是有残留的,除非你把RecyclerView的实体也放到adapter 里面去了,就当我没说这话。