为什么 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.

的大小