在 DiffUtil 更改后,带有 StaggeredGridLayoutManager 的 RecylerView 跳转到 2 个元素
RecylerView with StaggeredGridLayoutManager jumping to 2 element after DiffUtil change
我有 2 列 RecyclerView
基于 StaggeredGridLayoutManager
。
当更改第 1 项的内容并触发 DiffUtil
时,RecyclerView 会跳转到第 2 项。但是当向上滚动时,可以看到 1 个元素和空的 space,在滚动期间项目正在转换为自然顺序。此外,差异列表中的项目数量是相同的。
如何避免这种烦人的行为并在 diffUtil 期间保持滚动位置?
val layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
recyclerView.layoutManager = layoutManager
recyclerView.itemAnimator = null
recyclerView.setHasFixedSize(true)
recyclerView.setItemViewCacheSize(if (App.isTablet()) 3 else 2)
public void diffUpdate(List<T> newList) {
if (getCollection().size() == 0) {
addAll(newList);
notifyDataSetChanged();
} else {
DiffCallback diffCallback = new DiffCallback<T>(getCollection(), newList);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
clear();
addAll(newList);
diffResult.dispatchUpdatesTo(this);
}
}
问题出在 DiffCallback 的实施上。早些时候我使用了哈希:
@Override public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
T oldItem = oldList.get(oldItemPosition);
T newItem = newList.get(newItemPosition);
boolean areTheSameInstance = oldItem == newItem;
boolean hasTheSameType = oldItem.getClass().equals(newItem.getClass());
boolean hasTheSameHash = oldItem.hashCode() == newItem.hashCode();
return areTheSameInstance || hasTheSameType && hasTheSameHash;
}
这会触发 RecyclerView 中整个视图的重新创建,并且可能会在 StaggeredGridLayoutManager 中进行测量。
改成id校验后,diffCalbback开始只触发RecyclerView中view的渲染。
return ((Model) oldItem).id() == ((Model) newItem).id();
我有 2 列 RecyclerView
基于 StaggeredGridLayoutManager
。
当更改第 1 项的内容并触发 DiffUtil
时,RecyclerView 会跳转到第 2 项。但是当向上滚动时,可以看到 1 个元素和空的 space,在滚动期间项目正在转换为自然顺序。此外,差异列表中的项目数量是相同的。
如何避免这种烦人的行为并在 diffUtil 期间保持滚动位置?
val layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
recyclerView.layoutManager = layoutManager
recyclerView.itemAnimator = null
recyclerView.setHasFixedSize(true)
recyclerView.setItemViewCacheSize(if (App.isTablet()) 3 else 2)
public void diffUpdate(List<T> newList) {
if (getCollection().size() == 0) {
addAll(newList);
notifyDataSetChanged();
} else {
DiffCallback diffCallback = new DiffCallback<T>(getCollection(), newList);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
clear();
addAll(newList);
diffResult.dispatchUpdatesTo(this);
}
}
问题出在 DiffCallback 的实施上。早些时候我使用了哈希:
@Override public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
T oldItem = oldList.get(oldItemPosition);
T newItem = newList.get(newItemPosition);
boolean areTheSameInstance = oldItem == newItem;
boolean hasTheSameType = oldItem.getClass().equals(newItem.getClass());
boolean hasTheSameHash = oldItem.hashCode() == newItem.hashCode();
return areTheSameInstance || hasTheSameType && hasTheSameHash;
}
这会触发 RecyclerView 中整个视图的重新创建,并且可能会在 StaggeredGridLayoutManager 中进行测量。
改成id校验后,diffCalbback开始只触发RecyclerView中view的渲染。
return ((Model) oldItem).id() == ((Model) newItem).id();