为什么 DefaultItemAnimator 会强制更改的 ViewHolders 重新创建?
Why is DefaultItemAnimator forcing changed ViewHolders to recreate?
嘿,基本上我最近 运行 遇到了 RecyclerView
的问题(我遇到的问题在此处描述:)。我发现 RecyclerView
中的 ItemAnimator
决定是否只需要反弹已更改的 ViewHolder
或创建新的 ViewHolder 并交叉淡入淡出。
这篇文章解释了一些事情:
https://medium.com/android-news/anatomy-of-recyclerview-part-1-a-search-for-a-viewholder-continued-d81c631a2b91
我假设这是决定应该发生什么的 DefaultItemAnimator 的一部分:
/**
* {@inheritDoc}
* <p>
* If the payload list is not empty, DefaultItemAnimator returns <code>true</code>.
* When this is the case:
* <ul>
* <li>If you override {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}, both
* ViewHolder arguments will be the same instance.
* </li>
* <li>
* If you are not overriding {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)},
* then DefaultItemAnimator will call {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int)} and
* run a move animation instead.
* </li>
* </ul>
*/
@Override
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder,
@NonNull List<Object> payloads) {
return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads);
}
现在我的问题的解决方案是用一些任意有效负载调用 onItemRangeChanged()
,它总是会重用 ViewHolder
。
我的问题:
现在我想知道为什么以及什么时候重新创建整个 ViewHolder
并交叉淡化它比只更新它的特定部分更好?在上面提到的交叉引用问题中,我只是改变了 ViewHolder 的一小部分的可见性,但整个东西都被重新创建了,我认为这在性能方面更差吗?
请记住 RecyclerView
可以有多种项目视图类型。当 notifyItemChanged
导致视图类型更改时,无论有效负载如何,viewholder 都没有资格重用。
通过替换 viewholders,动画师在这种情况下保持了统一的行为。
此外,通过更新 ViewHolder,它们将不会经历人们在布置新项目时可能期望的适配器 onViewAttachedToWindow(holder)
以及为新项目调用的 onViewRecycled(holder)
& onViewDetachedFromWindow(holder)
正在删除。
附带说明一下,如果您在后续范围更新(无负载)期间遇到 onCreateViewHolder
调用,您可能应该增加 RecyclerView.RecycledViewPool
.
的大小
嘿,基本上我最近 运行 遇到了 RecyclerView
的问题(我遇到的问题在此处描述:RecyclerView
中的 ItemAnimator
决定是否只需要反弹已更改的 ViewHolder
或创建新的 ViewHolder 并交叉淡入淡出。
这篇文章解释了一些事情: https://medium.com/android-news/anatomy-of-recyclerview-part-1-a-search-for-a-viewholder-continued-d81c631a2b91
我假设这是决定应该发生什么的 DefaultItemAnimator 的一部分:
/**
* {@inheritDoc}
* <p>
* If the payload list is not empty, DefaultItemAnimator returns <code>true</code>.
* When this is the case:
* <ul>
* <li>If you override {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}, both
* ViewHolder arguments will be the same instance.
* </li>
* <li>
* If you are not overriding {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)},
* then DefaultItemAnimator will call {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int)} and
* run a move animation instead.
* </li>
* </ul>
*/
@Override
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder,
@NonNull List<Object> payloads) {
return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads);
}
现在我的问题的解决方案是用一些任意有效负载调用 onItemRangeChanged()
,它总是会重用 ViewHolder
。
我的问题:
现在我想知道为什么以及什么时候重新创建整个 ViewHolder
并交叉淡化它比只更新它的特定部分更好?在上面提到的交叉引用问题中,我只是改变了 ViewHolder 的一小部分的可见性,但整个东西都被重新创建了,我认为这在性能方面更差吗?
请记住 RecyclerView
可以有多种项目视图类型。当 notifyItemChanged
导致视图类型更改时,无论有效负载如何,viewholder 都没有资格重用。
通过替换 viewholders,动画师在这种情况下保持了统一的行为。
此外,通过更新 ViewHolder,它们将不会经历人们在布置新项目时可能期望的适配器 onViewAttachedToWindow(holder)
以及为新项目调用的 onViewRecycled(holder)
& onViewDetachedFromWindow(holder)
正在删除。
附带说明一下,如果您在后续范围更新(无负载)期间遇到 onCreateViewHolder
调用,您可能应该增加 RecyclerView.RecycledViewPool
.