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.