为什么多次调用 Recyclerview 适配器 onBindViewHolder?

Why Recyclerview adapter onBindViewHolder is called more than once?

我在回收站视图中使用 this tutorial to implement DiffUtil。我的目标是将单个项目添加到 recyclerview 的底部,而不重新加载 recyclerview 的其余部分。我使用 firestore addSnapshotListener 来调用适配器。问题是 onBindViewHolder 被多次调用(即列表中没有项目)。我认为使用 DiffUtil 时不会发生这种情况,对吗?它应该只为添加到 recyclerview 的项目调用 onBindViewHolder,对吗?

这是我调用适配器的代码:

@Override
protected void onStart()
{
    super.onStart();

    reference
        .addSnapshotListener((Activity)context, new EventListener<QuerySnapshot>()
        {
            @Override
            public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots,
                                @Nullable FirebaseFirestoreException e)
            {
                if (e != null)
                {
                    Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
                    return;
                }

                CommentsListAdapter adapter = new CommentsListAdapter(context);
                commentsRecyclerView.setAdapter(adapter);

                comments = new ArrayList<>();
                for (QueryDocumentSnapshot snapshot : queryDocumentSnapshots)
                {
                    Comment comment = snapshot.toObject(Comment.class).withId(snapshot.getId());
                    comments.add(comment);
                }
                adapter.submitList(comments);
                commentsRecyclerView.smoothScrollToPosition(adapter.getItemCount());
            }
        });
}

这是适配器 class:

class CommentsListAdapter extends ListAdapter<Comment, CommentsListAdapter.CommentsViewHolder>
    {
        private Context context;

        protected CommentsListAdapter(Context context)
        {
            super(DIFF_CALLBACK);
            this.context = context;
        }

        private static final DiffUtil.ItemCallback<Comment> DIFF_CALLBACK = new DiffUtil.ItemCallback<Comment>()
        {
            @Override
            public boolean areItemsTheSame(@NonNull Comment oldItem, @NonNull Comment newItem)
            {
                return oldItem.commentId.equals(newItem.commentId);
            }

            @Override
            public boolean areContentsTheSame(@NonNull Comment oldItem, @NonNull Comment newItem)
            {
                return oldItem.commentId.equals(newItem.commentId);
            }
        };

        @NonNull
        @Override
        public CommentsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
        {
            View itemView = LayoutInflater.from(context)
                    .inflate(R.layout.comment_list_item, parent, false);
            return new CommentsViewHolder(itemView);
        }

        @Override
        public void onBindViewHolder(@NonNull final CommentsViewHolder holder, int position)
        {
            System.out.println("POSITION: " + position);
            holder.commentText.setText(getItem(position).getComment());
            holder.timeText.setText(getItem(position).getCommentDateCreated());
        }

        public class CommentsViewHolder extends RecyclerView.ViewHolder
        {
            private TextView commentText;
            private TextView timeText;

            public CommentsViewHolder(@NonNull View itemView)
            {
                super(itemView);
                commentText = itemView.findViewById(R.id.commentText);
                timeText = itemView.findViewById(R.id.timeText);
            }
        }
    }

我是 DiffUtil 的新手。那么,它应该发生吗?还是代码有问题?

每次从 Firestore 收到回调时,您都会重新创建 CommentsListAdapter

将适配器拉入您 Activity 中的全局变量,并在 Firestore 回调中仅调用 adapter.submitList(comments);

您编辑的代码:

CommentsListAdapter adapter = new CommentsListAdapter(context);
@Override
protected void onStart()
{
    super.onStart();
    commentsRecyclerView.setAdapter(adapter);
    reference
        .addSnapshotListener((Activity)context, new EventListener<QuerySnapshot>()
        {
            @Override
            public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots,
                                @Nullable FirebaseFirestoreException e)
            {
                if (e != null)
                {
                    Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
                    return;
                }

                comments = new ArrayList<>();
                for (QueryDocumentSnapshot snapshot : queryDocumentSnapshots)
                {
                    Comment comment = snapshot.toObject(Comment.class).withId(snapshot.getId());
                    comments.add(comment);
                }
                adapter.submitList(comments);
                commentsRecyclerView.smoothScrollToPosition(adapter.getItemCount());
            }
        });
}