DiffUtil 不调用 onBindView 或刷新 ViewHolder
DiffUtil not calling onBindView or refreshing ViewHolder
我尝试使用 DiffUtil 方法更新我的列表,该列表始终包含 30 个项目,现在每个项目数据每分钟更新一次,但无法判断是否所有项目的数据都会更新,以避免滥用 notifyDataSetChanged()
我创建了一个 class 扩展 DiffUtil。
public class DifUtil extends DiffUtil.Callback {
private final List<Asset> oldList, newList;
public DifUtil(List<Asset> newList, List<Asset> oldList) {
this.oldList = oldList;
this.newList = newList;
}
@Override
public int getOldListSize() {
return oldList.size();
}
@Override
public int getNewListSize() {
return newList.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).getId().equals(newList.get(newItemPosition).getId());
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).equals(newList.get(newItemPosition));
}
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
//you can return particular field for changed item.
return super.getChangePayload(oldItemPosition, newItemPosition);
}
}
添加新的 public 函数来通知适配器
public void updateList(List<Asset> newList) {
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DifUtil(newList, this.assetList));
this.assetList.clear();
this.assetList.addAll(newList);
diffResult.dispatchUpdatesTo(this);
}
覆盖另一个 onBindViewHolder(不确定在不使用负载时是否需要)
onBindViewHolder(@NonNull AssetsAdapter.ViewHolder holder, int position, @NonNull List<Object> payloads)
然后通过调用
更新列表
adapter.updateList(newAssetList);
列表的更新有效,但我只能通过滚动列表来查看这些新值,即使不回收视图(滚动时)我也需要查看更新,就像 notifyItemChanged()
.
据我所知,调用 dispatchUpdatesTo
应该处理和更新视图及其数据,或者我在这里遗漏了什么,请赐教。
我通过关注此博客及其实现 DiffUtil 的方式设法使其工作。
https://www.journaldev.com/20873/android-recyclerview-diffutil
但是我没有执行克隆部分,因为它与我的情况无关。
奖金
有一个已知的错误,更新使列表在底部滚动。我通过在这个 SO 答案中使用 LayoutManager
保存滚动状态来摆脱这个。
所以我的适配器 DiffUtil 更新部分将是这个
public void updateList(List<Asset> newList) {
Parcelable recyclerViewState = layoutManager.onSaveInstanceState();
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DifUtil(newList, this.assetList));
diffResult.dispatchUpdatesTo(this);
this.assetList.clear();
this.assetList.addAll(newList);
layoutManager.onRestoreInstanceState(recyclerViewState);
}
我尝试使用 DiffUtil 方法更新我的列表,该列表始终包含 30 个项目,现在每个项目数据每分钟更新一次,但无法判断是否所有项目的数据都会更新,以避免滥用 notifyDataSetChanged()
我创建了一个 class 扩展 DiffUtil。
public class DifUtil extends DiffUtil.Callback {
private final List<Asset> oldList, newList;
public DifUtil(List<Asset> newList, List<Asset> oldList) {
this.oldList = oldList;
this.newList = newList;
}
@Override
public int getOldListSize() {
return oldList.size();
}
@Override
public int getNewListSize() {
return newList.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).getId().equals(newList.get(newItemPosition).getId());
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).equals(newList.get(newItemPosition));
}
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
//you can return particular field for changed item.
return super.getChangePayload(oldItemPosition, newItemPosition);
}
}
添加新的 public 函数来通知适配器
public void updateList(List<Asset> newList) {
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DifUtil(newList, this.assetList));
this.assetList.clear();
this.assetList.addAll(newList);
diffResult.dispatchUpdatesTo(this);
}
覆盖另一个 onBindViewHolder(不确定在不使用负载时是否需要)
onBindViewHolder(@NonNull AssetsAdapter.ViewHolder holder, int position, @NonNull List<Object> payloads)
然后通过调用
更新列表adapter.updateList(newAssetList);
列表的更新有效,但我只能通过滚动列表来查看这些新值,即使不回收视图(滚动时)我也需要查看更新,就像 notifyItemChanged()
.
据我所知,调用 dispatchUpdatesTo
应该处理和更新视图及其数据,或者我在这里遗漏了什么,请赐教。
我通过关注此博客及其实现 DiffUtil 的方式设法使其工作。 https://www.journaldev.com/20873/android-recyclerview-diffutil
但是我没有执行克隆部分,因为它与我的情况无关。
奖金
有一个已知的错误,更新使列表在底部滚动。我通过在这个 SO 答案中使用 LayoutManager
保存滚动状态来摆脱这个。
所以我的适配器 DiffUtil 更新部分将是这个
public void updateList(List<Asset> newList) {
Parcelable recyclerViewState = layoutManager.onSaveInstanceState();
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DifUtil(newList, this.assetList));
diffResult.dispatchUpdatesTo(this);
this.assetList.clear();
this.assetList.addAll(newList);
layoutManager.onRestoreInstanceState(recyclerViewState);
}