user5590200
user5590200

Reputation: 33

RecyclerView adapter showing more images than it should be

I have a RecyclerView adapter that inflates another layout (child_layout.xml) into the main layout (main_layout.xml).

Here is the RecyclerView adapter:

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {

    private static Context context;
    private List<Message> mDataset;

    public RecyclerAdapter(Context context, List<Message> myDataset) {
        this.context = context;
        this.mDataset = myDataset;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener, View.OnClickListener {
        public TextView title;
        public LinearLayout placeholder;

        public ViewHolder(View view) {
            super(view);
            view.setOnCreateContextMenuListener(this);

            title = (TextView) view.findViewById(R.id.title);
            placeholder = (LinearLayout) view.findViewById(R.id.placeholder);
        }
    }

    @Override
    public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.main_layout, parent, false);
        ViewHolder vh = new ViewHolder((LinearLayout) view);

        return vh;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Message item = mDataset.get(position);

        holder.title.setText(item.getTitle());

        int numImages = item.getImages().size();

        if (numImages > 0) {
            View inflater = LayoutInflater.from(holder.placeholder.getContext()).inflate(R.layout.child_layout, holder.placeholder, false);
            ImageView image = (ImageView) inflater.findViewById(R.id.image);
            Glide.with(context)
                .load("http://www.website.com/test.png")
                .fitCenter()
                .into(image);
            holder.placeholder.addView(inflater);
        }
    }

    @Override
    public int getItemCount() {
        return mDataset.size();
    }

}

Here is main_layout.xml:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    <LinearLayout
        android:id="@+id/placeholder"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        />

    <TextView
        android:id="@+id/desc"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

</LinearLayout>

Here is child_layout.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

</LinearLayout>

The problem is, as I scroll through my app, some of the views are showing 2+ images (when the child_layout only has one ImageView):

https://i.sstatic.net/t4n2I.png

Why does this happen? Why do some views show more than one image when it should only be showing one?

Upvotes: 2

Views: 878

Answers (1)

Alex Kolpa
Alex Kolpa

Reputation: 187

onBindViewHolder is meant for binding data to the view you created in onCreateViewHolder (hence the name). You shouldn't inflate a new view every time in onBindViewHolder, because that takes away the large benefit of a RecyclerView, namely view recycling. What's causing the issue currently is that you inflate and add a child to a main view every time onBindViewHolder is called. This method can be called multiple times for a single view, meaning you're adding new child views every time it's called. You can fix this by only inflating the child view once inside onCreateViewHolder. Your conditional check in the binding suggests you don't want it visible at all times. What you could do there is call setVisibility on the child view to hide it if no images are present.

Upvotes: 2

Related Questions