Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remote Images in a ListView with ViewHolder pattern

Main question:

What is the most efficient bug free method of lazy loading remote images in a simple ListView adapter that utilizes the ViewHolder pattern?

I currently have an implementation that will first check a SoftReference Bitmap HashMap for a soft caches version of the image. If that fails I check my hard cache for a copy of the image. If that fails I get it from the web. I do all of this on a separate thread and in a queue to eliminate concurrent or duplicate downloads.

The problem is when loading through a callback. Because I utilize the ViewHolder pattern my views are constantly being recycled and I have not found a solid way to eliminate different images being randomly attached to my ImageViews. I do default to a default image before each load but because the views are being recycled so quickly "old" listeners apply onto my ImageView providing the wrong image which are then replaced with the correct image.

The only semi-solid solution I have found is to use the ViewHolder itself as the listener but this only makes the problem less apparent. It still happens on a fast scroll.

Any help would be appreciated.

Update:

https://github.com/DHuckaby/Prime

like image 382
HandlerExploit Avatar asked Oct 05 '11 20:10

HandlerExploit


1 Answers

I have found a solution to the image switching problem and I will provide a code chunk below. I will not accept it yet though because I do not know if this is the most efficient method which is my original question. If this is implemented correctly it will work perfectly.

 public void getView(int position, View convertView, ViewGroup parent) {

     ViewHolder holder;
     if (convertView == null) {

     ...

     String imagePath = insertImageUrlHere();
     Object tag = holder.userThumb.getTag();
     if (tag != null && tag.equals(imagePath)) {
          // Do nothing
     } else {
          holder.userThumb.setTag(imagePath);
          holder.userThumb.setImageResource(R.drawable.default_image);
          AsynchronousImageLoadingUtility.load(imagePath, holder);
     }

     ...

     return convertView;
 }

 private static class ViewHolder implements AsynchronousImageLoadingUtilityCallback {

     private ImageView userThumb;

     @Override
     public void onImageLoad(String source, Bitmap image) {
          if (image != null && userThumb.getTag().equals(source)) {
               userThumb.setImageBitmap(image);
          }
     }
 }
like image 84
HandlerExploit Avatar answered Nov 08 '22 20:11

HandlerExploit