Using Android Universal Image Loader and RecyclerView to asynchronously load images, I'm getting the same error as other people, where the images get mixed up; until they have all loaded an are cached.
Code for the adapter:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.media.Image;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import com.nostra13.universalimageloader.utils.MemoryCacheUtils;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import romina.theftest.connectivity.ImgDownloader;
/**
* Created by romin on 18/1/2016.
*/
public class ProductRecyclerViewAdapter extends RecyclerView.Adapter {
private List<Product> mValues;
private Context mContext;
private View.OnClickListener mListener;
// Allows to remember the last item shown on screen
private int lastPosition = -1;
private final String OLD_DOMAIN = "";
private final String NEW_DOMAIN = "";
public ProductRecyclerViewAdapter(Context mContext, View.OnClickListener mListener) {
this.mContext = mContext;
this.mListener = mListener;
}
public ProductRecyclerViewAdapter(List<Product> mValues, Context mContext, View.OnClickListener mListener) {
this(mContext, mListener);
this.mListener = mListener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.product_list_item, parent, false);
Log.d(ProductRecyclerViewAdapter.class.getSimpleName(), "onCreateViewHolder");
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
ViewHolder actualViewHolder = (ViewHolder) holder;
actualViewHolder.mItem = mValues.get(position);
actualViewHolder.mIdView.setText("" + mValues.get(position).getName());
Log.d(ProductRecyclerViewAdapter.class.getSimpleName(), "onBindViewHolder pos " + position);
ImageLoader imageLoader = ImageLoader.getInstance(); // Get singleton instance
final String finalImgURL = mValues.get(position).getImgURL().toString().replaceAll(OLD_DOMAIN, NEW_DOMAIN);
imageLoader.displayImage(finalImgURL, actualViewHolder.mImgView);
setAnimation(actualViewHolder.mContentView, position);
}
public void setDataSet(List<Product> newValues) {
mValues = newValues;
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return mValues == null ? 0 : mValues.size();
}
/**
* Here is the key method to apply the animation
*/
private void setAnimation(View viewToAnimate, int position) {
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition) {
Animation animation = AnimationUtils.loadAnimation(mContext, android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
public final View mView;
public final TextView mIdView;
public final ImageView mImgView;
public final TextView mContentView;
public Product mItem;
public ViewHolder(View view) {
super(view);
mView = view;
mIdView = (TextView) view.findViewById(R.id.product_quantity_title);
mContentView = (TextView) view.findViewById(R.id.product_quantity_title);
mImgView = (ImageView) view.findViewById(R.id.product_quantity_image);
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (null != mListener) {
mListener.onClick(v);
}
}
});
}
@Override
public String toString() {
return super.toString() + " '" + mContentView.getText() + "'";
}
}
}
I know it has to be something in onBindViewHolder
, since it's called for updating every view but I'm not updating the ImageView
properly.
It doesn't have to do with the library. The same behaviour was happening when doing lazy loading without caching the images. The error is because I don't know how to update the ImageView
in onBindViewHolder
.
Thanks!