0

I am using ion library to load images in recyclerview. But i am facing with a problem. RecyclerView is repeating items. When the image is not loaded in new item it shows previously loaded images. I need to show ProgressBar if image is not loaded. How to achieve this.

Here is my Adapter class:

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

private String[] links;
private Context context;
private int screen_width;

public RecyclerViewAdapter(Context context, String[] links, int screen_width) {
    this.links = links;
    this.context = context;
    this.screen_width = screen_width;
}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(context).inflate(R.layout.list_item,viewGroup,false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull ViewHolder viewHolder, final int i) {
    loadImage(i, viewHolder);
}

private void loadImage(final int pos, final ViewHolder holder) {

    Ion.with(context)
            .load(links[pos])
            .withBitmap()
            .placeholder(R.drawable.icon_download_active)
            .error(R.drawable.icon_could_not_download)
            .fadeIn(true)
            .asBitmap()
            .setCallback(new FutureCallback<Bitmap>() {
                @SuppressLint("SetTextI18n")
                @Override
                public void onCompleted(Exception e, Bitmap result) {
                    if ( e != null ) {
                        Log.i("IMAGE_LOADER_EV","Failed to load image \n Error:"+e.toString());
                    } else {
                        int h = (screen_width * result.getHeight()) / result.getWidth();
                        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(screen_width,h);
                        params.setMargins(0,0,0,dpToPx(context));

                        holder.image.setLayoutParams(params);
                        holder.image.setImageBitmap(result);
                    }
                }
            });

}

private static int dpToPx(Context context) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, (float) 5, context.getResources().getDisplayMetrics());
}

@Override
public int getItemCount() {
    return links.length;
}

class ViewHolder extends RecyclerView.ViewHolder {
    ImageView image;
    TextView dimens;
    ProgressBar progressBar;
    ViewHolder(View view) {
        super(view);
        image = view.findViewById(R.id.image);
        dimens = view.findViewById(R.id.dimens);
        progressBar = view.findViewById(R.id.progress_bar);
    }
}

}

Recycler shows previous items when the new image is not loaded. So how to solve this problem?

2 Answers2

0

Finally found solution. Just add following codes to Adapter class:

@Override
public long getItemId(int position) {
    return (long) (position);
}
@Override
public int getItemViewType(int position) {
    return position;
}
0

Use:

Ion.with(imageView)

Then remove where you manually set the image in the ImageView in the callback.

.setCallback(...)

Since you are using the callback to manage populating the ImageView, you're creating a race condition where the ImageView is loaded by multiple different items as it is recycled.

Using Ion.with(imageView) allows Ion to track the ImageViews in your RecyclerView and cancel image loads as the ImageViews get recycled.

See sample:

https://github.com/koush/ion#load-an-image-into-an-imageview

koush
  • 2,972
  • 28
  • 31