一、RecycleView更新Item闪烁
项目中有Recycle更新部分item的需求,发现item居然闪烁了,给用户体验不是很好。回想QQ微信中也聊天列表也没出现这么长时间的闪烁,好奇它背后是怎么做到的,于是便查了一下,原来RecycleView onBindViewHolder重复调用,新的holder替换旧的holder替换存在一个过渡动画,这样就导致了闪烁。
知道原因了也就有解决方法:
法1.
去除itemAnimator
recyclerView.setItemAnimator(null);
法2
将动画关闭,动画时间设置为0。这个方法不是很管用,只针对单个item还是OK的。但如果是多个item,实际测试还是会出现快速的闪烁一下,建议使用法1。
recyclerView.getItemAnimator().setAddDuration(0);
recyclerView.getItemAnimator().setChangeDuration(0);
recyclerView.getItemAnimator().setMoveDuration(0);
recyclerView.getItemAnimator().setRemoveDuration(0);
((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
二、RecycleView好伴侣DiffUtil使用
参考: 【Android】RecyclerView的好伴侣:详解DiffUtil
首先DiffUtil是RecycleView自带的一个工具类,无需引入新的库。它帮我自动自动计算新老数据集的差异,并根据差异情况自动调用notifyItemRangeInserted notifyItemRangeRemoved notifyItemMoved notifyItemRangeChanged
这四个方法,这样我们就不需要无脑的调用notifyDataSetChanged方法了。
使用步骤:
1、使用自己的实体类,实现HomeDeviceDiff
import androidx.recyclerview.widget.DiffUtil;
import com.hynson.entity.HomeDevice;
import java.util.List;
public class HomeDeviceDiff extends DiffUtil.Callback {
private List<HomeDevice> oldDatas,newDatas;
public HomeDeviceDiff(List<HomeDevice> oldDatas, List<HomeDevice> newDatas) {
this.oldDatas = oldDatas;
this.newDatas = newDatas;
}
@Override
public int getOldListSize() {
return oldDatas != null ? oldDatas.size() : 0;
}
@Override
public int getNewListSize() {
return newDatas != null ? newDatas.size() : 0;
}
@Override
public boolean areItemsTheSame(int oldPos, int newPos) {
HomeDevice oldBean = oldDatas.get(oldPos);
HomeDevice newBean = newDatas.get(newPos);
return oldBean.getId().equals(newBean.getId()) && oldBean.getDevType().equals(newBean.getDevType())
&& oldBean.getTitle().equals(newBean.getTitle()) && oldBean.getState().equals(newBean.getState())
&& oldBean.getWorkState().equals(newBean.getWorkState()) && oldBean.getStateTip().equals(newBean.getStateTip());
}
@Override
public boolean areContentsTheSame(int oldPos, int newPos) {
HomeDevice oldBean = oldDatas.get(oldPos);
HomeDevice newBean = newDatas.get(newPos);
return oldBean.getId().equals(newBean.getId()) && oldBean.getDevType().equals(newBean.getDevType())
&& oldBean.getTitle().equals(newBean.getTitle()) && oldBean.getState().equals(newBean.getState())
&& oldBean.getWorkState().equals(newBean.getWorkState()) && oldBean.getStateTip().equals(newBean.getStateTip());
}
}
2、在我们更新适配器的地方,调用如下代码
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new HomeDeviceDiff(mView.getHomeDeviceAdapter().getmDeviceList(), devices), true);
diffResult.dispatchUpdatesTo(mView.getHomeDeviceAdapter());
mView.getHomeDeviceAdapter().updateData(devices);