androidmvvmandroid-recyclerviewandroid-volleynetworkimageview

NetworkImageView in RecyclerView cause displaying issues due to recycling


So, I use MVVM, Data Binding, RecyclerView and Volley ImageLoader with NetworkImageView.

And I basically trying to display a feed with some items (not all) containing NetworkImageViews (Using Volley & ImageLoader).

The problem is that my holder is recycled, and my "current" NetworkImageView is displaying a previously asked imageUrl (asked for another card).

I did some research, and I have to cancel the request if my holder is recycled. I get the point, I don't really see how to do this in my current code and doing it CLEAN.

PS : I don't want to avoid the recycling of my RecyclerView (there is no point to use it then).

I am really surprised that there is no way with ImageLoader/ImageContainer to handle this properly by default. If there is a simple, working and easily maintainable way to do this with another library (Fresco, Picasso, Glide, UIL, ...), why not.

There is my adapter :

public final class FeedAdapter extends RecyclerView.Adapter<FeedAdapter.BindingHolder> {

    private Context context;
    private List<FeedEntry> feedEntries;

    public FeedAdapter(Context _context, List<FeedEntry> _feedEntries) {
        this.context = _context;
        this.feedEntries = _feedEntries;
    }

    @Override
    public BindingHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        if (viewType == FeedEntry.TYPE_IMAGE_ID) {
            ItemFeedEntryImageBinding itemFeedEntryImageBinding = DataBindingUtil.inflate(
                    LayoutInflater.from(parent.getContext()),
                    R.layout.item_feed_entry_image,
                    parent,
                    false);
            return new BindingHolder(itemFeedEntryImageBinding);
        }
    }

    @Override
    public void onBindViewHolder(BindingHolder holder, int position) {

        if (getItemViewType(position) == FeedEntry.TYPE_IMAGE_ID) {
            ItemFeedEntryImageBinding feedEntryImageBinding = (ItemFeedEntryImageBinding) holder.binding;
            feedEntryImageBinding.setViewModel(new FeedEntryViewModel(this.context, this.feedEntries.get(position)));
        }
    }


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

    @Override
    public int getItemViewType(int position) {
        // Code...
        return FeedEntry.TYPE_IMAGE_ID;
    }

    public static class BindingHolder extends RecyclerView.ViewHolder {
        private ViewDataBinding binding;

        public BindingHolder(ItemFeedEntryImageBinding binding) {
            super(binding.feedEntryCard);
            this.binding = binding;
        }
    }
}

And there is the main content of my ViewModel

@BindingAdapter({"bind:contentImageUrlVolley"})
public static void loadContentImageVolley(NetworkImageView view, String url) {
    //view.setImageUrl(null, MyApplication.getInstance().getImageLoader()); Do not solve my issue
    view.setImageUrl(url, MyApplication.getInstance().getImageLoader());
}

Solution

  • I found out that using Fresco instead of Volley/ImageLoader solve the problem.