Wrong adapter when using RecycledViewPool

161 views Asked by At

We have a recycler view and inside it we have another recycler view. For the second recycler view, we are using a viewpool. Our nested recycler view is a list of little images and when the user click on one, it should open. In most part of cases, it is working. But when we have a big list of these little images, the full screen opening (it is what happens when the user click on one little image) is not working and looks like that the reason is because it is using the wrong instance of nested adapter. When I say wrong, it is not the wrong class but the wrong reference. The itens that are opening are using an instance of the adapter and those that don`t, are using another.

Following is our "parent" ViewHolder, where we create the nested adapter and set a viewpool:

 static class ChecklistVisualizacaoViewHolder extends RecyclerView.ViewHolder implements
            ThumbnailMediaChecklistAdapter.ThumbnailMediaChecklistListener {
        @NonNull
        private final TextView mTxtPergunta;
        @NonNull
        private final TextView mTxtDescricaoNok;
        @NonNull
        private final View mViewLateral;
        @NonNull
        private final RecyclerView mRecyclerThumbnailsMedia;
        @Nullable
        private final ChecklistVisualizacaoListener mListener;

        ChecklistVisualizacaoViewHolder(final View view,
                                        @NonNull final RecyclerView.RecycledViewPool viewPool,
                                        @Nullable final ChecklistVisualizacaoListener listener) {
            super(view);
            mListener = listener;
            mTxtPergunta = view.findViewById(R.id.txt_pergunta);
            mTxtDescricaoNok = view.findViewById(R.id.txt_descricaoNok);
            mViewLateral = view.findViewById(R.id.view_itemRespostaChecklist);
            mRecyclerThumbnailsMedia = view.findViewById(R.id.recycler_thumbnailsMedia);

            final ThumbnailMediaChecklistAdapter adapter = new ThumbnailMediaChecklistAdapter(
                    new ArrayList<>(),
                    this);
            mRecyclerThumbnailsMedia.addItemDecoration(
                    new ThumbnailMediaChecklistItemDecoration(view.getContext()));
            mRecyclerThumbnailsMedia.setRecycledViewPool(viewPool);
            mRecyclerThumbnailsMedia.setAdapter(adapter);
        }

        @Override
        public void onMediaClicked(@NonNull final List<MediaChecklistItemAdapter> allMedias,
                                   @NonNull final MediaChecklistItemAdapter mediaClicked) {
            if (mListener != null) {
                mListener.onClickMedia(getAdapterPosition(), allMedias, mediaClicked);
            }
        }
    }

And here is the nested Adapter:

public final class ThumbnailMediaChecklistAdapter extends
        BaseAdapter<ThumbnailMediaChecklistAdapter.ThumbnailMediaChecklistViewHolder> implements
        OnItemClickListener {

    @NonNull
    private final List<MediaChecklistItemAdapter> mMedias;
    @NonNull
    private final ThumbnailMediaChecklistListener mListener;

    public interface ThumbnailMediaChecklistListener {
        void onMediaClicked(@NonNull final List<MediaChecklistItemAdapter> allMedias,
                            @NonNull final MediaChecklistItemAdapter mediaClicked);
    }

    public ThumbnailMediaChecklistAdapter(@NonNull final List<MediaChecklistItemAdapter> medias,
                                          @NonNull final ThumbnailMediaChecklistListener listener) {
        mMedias = medias;
        mListener = listener;
    }

    @NonNull
    @Override
    public ThumbnailMediaChecklistViewHolder onCreateViewHolder(@NonNull final ViewGroup parent,
                                                                final int viewType) {
        final View view = LayoutInflater
                .from(parent.getContext())
                .inflate(R.layout.item_thumbnail_media_checklist, parent, false);
        return new ThumbnailMediaChecklistViewHolder(view, this);
    }

    @Override
    public void onBindViewHolder(@NonNull final ThumbnailMediaChecklistViewHolder holder,
                                 final int position) {
        final MediaChecklistItemAdapter item = mMedias.get(position);
        if (item.getMediaType() == MediaChecklistType.IMAGE) {
            Picasso.with(holder.mImgThumbnail.getContext())
                    .load(item.getMediaUri())
                    .into(holder.mImgThumbnail);
        }
    }

    @Override
    public int getItemCount() {
        //noinspection ConstantConditions
        return mMedias != null ? mMedias.size() : 0;
    }

    @Override
    public void onItemClick(final View view, final int position) {
        //noinspection ConstantConditions
        if (mListener != null && position >= 0 && position < mMedias.size()) {
            mListener.onMediaClicked(mMedias, mMedias.get(position));
        }
    }

    public void clearMedias() {
        mMedias.clear();
        notifyDataSetChanged();
    }

    public void addMedia(@NonNull final MediaChecklistItemAdapter media) {
        mMedias.add(media);
        notifyItemInserted(mMedias.size() - 1);
    }

    public void replaceMedias(@NonNull final List<MediaChecklistItemAdapter> medias) {
        mMedias.clear();
        mMedias.addAll(medias);
        notifyDataSetChanged();
    }

    static class ThumbnailMediaChecklistViewHolder extends RecyclerView.ViewHolder implements
            View.OnClickListener {
        @Nullable
        private final OnItemClickListener mOnItemClickListener;
        @NonNull
        private final ImageView mImgThumbnail;

        ThumbnailMediaChecklistViewHolder(final View itemView,
                                          @Nullable final OnItemClickListener listener) {
            super(itemView);
            mOnItemClickListener = listener;
            mImgThumbnail = itemView.findViewById(R.id.img_thumbnail);
            itemView.findViewById(R.id.layout_clickable).setOnClickListener(this);
        }

        @Override
        public void onClick(final View view) {
            final int adapterPosition = getAdapterPosition();
            if (mOnItemClickListener != null && adapterPosition != RecyclerView.NO_POSITION) {
                mOnItemClickListener.onItemClick(view, adapterPosition);
            }
        }
    }
}

Debugging the code, when I click on an item that is not working, I can check that the instance of adapter from this item is different of the instance of adapter of an item that is working.

This part of code is what is called for the click. The opening is not working because position is bigger than mMedias.size(), because the instance of this adapter is not the right one:

@Override
public void onItemClick(final View view, final int position) {
    //noinspection ConstantConditions
    if (mListener != null && position >= 0 && position < mMedias.size()) {
        mListener.onMediaClicked(mMedias, mMedias.get(position));
    }
}

If I remove this verification, an exception occurs, because the position doesn't exists on the medias list.

I don't know if I'm using it in the correct way or if I need to add something else.

0

There are 0 answers