RecycleView刷新某一个Item,或这某一个Item中某一个View。
这样的需求,在实际的开发中是很普遍的。
在数据变化后需要刷新列表。
刷新列表有三种方式:
前两种大家应该很熟,第三中会有点陌生。
那么这三种方式,有什么却别呢?
public void updateData() {
notifyDataSetChanged();
}
public void updateData(int pos) {
notifyItemChanged(pos);
}
public void updateData(int pos, Object payload) {
notifyItemChanged(pos, payload);
}
先看第一种:notifyDataSetChanged()
这个就属于暴力刷新了,他会刷新整个可见的item列表。刷新效率很差。我只想要更新某个Item中的TextView,但是这种方式,会导致全部Item列表重新绘制一遍。
findViewById(R.id.button1).setOnClickListener(v -> {
int pos = 0;
Person person = list.get(pos);
person.name = "update";
person.age = 44;
adapter.updateData();
});
public void updateData() {
notifyDataSetChanged();
}
从日志中可以看出来,这种刷新方式,会把所有的Item重新绘制一遍。
再看第二种刷新方式: notifyItemChanged(pos);
findViewById(R.id.button2).setOnClickListener(v -> {
int pos = 0;
Person person = list.get(pos);
person.name = "update";
person.age = 55;
adapter.updateData(pos);
});
public void updateData(int pos) {
notifyItemChanged(pos);
}
这种方式会根据传进来的pos来刷新对应的某一个Item。但是Item中会包含其他的View,
也会导致其他的View跟着刷新,虽然有了较大的优化,但是还是有一些画蛇添足。
看日志:
从日志可以看出,的确刷只刷新了某一个Item。但是整个Item中定义的View也会跟着一起绘制,
会执行onLayout,onMeasure,onDraw三个绘制方式。
我只修改了某个View,只需要重新绘制更新的VIew就行,没有更新的不用跟着计算。
再看第三种方式,
传进去了一个标识,需要在重写onBindViewHolder的重载方法。
findViewById(R.id.button3).setOnClickListener(v -> {
int pos = 0;
Person person = list.get(pos);
person.name = "payload";
person.age = 66;
adapter.updateData(pos, "name");
});
public void updateData(int pos, Object payload) {
notifyItemChanged(pos, payload);
}
根据传进来的标识,只改变,需要修改的VIew。前提是要修改的View的大小不会变化,只改变状态,因为Item中其他的View不刷新。如果大小改变的话,可能会导致布局跟着变,这时就得需要item去重新计算来绘制了。
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position,
@NonNull List
看日志:
确实只修改了需要修改的View,并没有导致整个View进行重新绘制。
代码下载:https://download.csdn.net/download/niuyongzhi/88382724