Почему адаптер Recyclerview onBindViewHolder вызывается более одного раза?

Я использую это руководство для реализации DiffUtil в моем обзоре утилит. Моя цель состоит в том, чтобы добавить один элемент в конец окна повторного просмотра, не перезагружая оставшуюся часть повторного просмотра. Я использовал fireStore addSnapshotListener для вызова адаптера. Проблема заключается в onBindViewHolder вызывается несколько раз (т. е. в списке нет ни одного элемента). Я не думаю, что это должно произойти при использовании DiffUtil, верно? Он должен вызывать 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 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. Итак, это должно произойти? Или что-то не так с кодом?

1 ответ

Решение

Каждый раз, когда вы получаете обратный вызов из Firestore, вы воссоздаете свой CommentsListAdapter

Вставьте адаптер в глобальную переменную в вашей деятельности и вызовите только adapter.submitList(comments); в обратном вызове Firestore

Ваш отредактированный код:

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());
            }
        });
}
Другие вопросы по тегам