Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView adapter showing wrong images

I have a RecyclerView adapter that looks like this:

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.message_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 test = LayoutInflater.from(holder.placeholder.getContext()).inflate(R.layout.images, holder.placeholder, false);
            ImageView image = (ImageView) test.findViewById(R.id.image);
            Glide.with(context)
                .load("http://www.website.com/test.png")
                .fitCenter()
                .into(image);
            holder.placeholder.addView(test);
        }
    }

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

}

However, some of the items in the RecyclerView are showing images when they shouldn't be. How can I stop this from happening?

I do the check if (numImages > 0) { in onBindViewHolder(), but that's still not stopping it from showing images for items that shouldn't have images.

like image 929
user5578746 Avatar asked Nov 20 '15 20:11

user5578746


3 Answers

You should set imageView.setImageDrawable (null) In onBindViewHolder() before setting the image using glide.

Setting image drawable to null fix the issue.

Hope it helps!

like image 146
Prashant Solanki Avatar answered Nov 20 '22 18:11

Prashant Solanki


The problem is in onBindViewHolder, here:

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

If numImages is equal to 0, you're simply allowing the previously started load into the view you're reusing to continue. When it finishes, it will still load the old image into your view. To prevent this, tell Glide to cancel the previous load by calling clear:

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

When you call into(), Glide handles canceling the old load for you. If you're not going to call into(), you must call clear() yourself.

Every call to onBindViewHolder must include either a load() call or a clear() call.

like image 43
Sam Judd Avatar answered Nov 20 '22 19:11

Sam Judd


I also had issues with RecyclerView showing wrong images. This happens because RecyclerView is not inflating view for every new list item: instead list items are being recycled.

By recycling views we can ruffly understand cloning views. A cloned view might have an image set from the previous interaction.

This is especially fair if your are using Picasso, Glide, or some other lib for async loading. These libs hold reference to an ImageView, and set an image on that refference when image is loaded.

By the time the image gets loaded, the item view might have gotten cloned, and the image is going to be set to the wrong clone.

To make a long story short, I solved this problem by restricting RecyclerView from cloning my item views:

setIsRecyclable(false)in ViewHolder constructor.

Now RecyclerView is working a bit slower, but at least the images are set right.

Or else cansel loading image in onViewRecycled(ViewHolder holde)

like image 11
алекс кей Avatar answered Nov 20 '22 19:11

алекс кей