为什么 DefaultItemAnimator 强制更改的 ViewHolders 重新创建?

时间:2021-02-27 11:04:04

标签: android android-recyclerview android-viewholder

嘿,基本上我最近遇到了 RecyclerView 的问题(这里描述了我遇到的问题:RecyclerView recreating ViewHolder instead of rebinding)。我发现 ItemAnimator 中的 RecyclerView 决定了更改的 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 一小部分的可见性,但整个事情都被重新创建了,我认为这在性能方面会更差吗?

1 个答案:

答案 0 :(得分:1)

请记住,RecyclerView 可以有多个项目视图类型。当 notifyItemChanged 导致视图类型更改时,无论负载如何,视图持有者都没有资格重用。

在这种情况下,动画师通过替换 viewholders 保持统一的行为。

此外,通过更新 ViewHolder,它们不会经历人们在布置新项目时可能期望的适配器 onViewAttachedToWindow(holder) 以及为正在删除的项目调用的 onViewRecycled(holder) & onViewDetachedFromWindow(holder) .

附带说明,如果您在后续范围更新(没有有效负载)期间遇到 onCreateViewHolder 调用,您可能应该增加 RecyclerView.RecycledViewPool 的大小。

相关问题