Imageview gets set multiple time using AsyncTask in Android
<p>I followed the procedure <a href="http://android-developers.blogspot.in/2010/07/multithreading-for-performance.html" rel="nofollow">here</a> and set up an easy AsyncTask Image downloader/loader for me. I call the download function from inside my GetView of the Adapter. Thus, everytime I scroll up or down, once the view goes out of screen, the images vanish only to be set again when I scroll back to that item. How do I stop this and, once I've all the images downloaded/cached, to set it. I don't want my ImageViews to be reset every single time. </p>

<p>This is the ImageManager:</p>

<pre><code>import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Stack;

import android.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;



public class ImageManager { 
      private HashMap&lt;String, Bitmap&gt; imageMap = new HashMap&lt;String, Bitmap&gt;(); 
      private File cacheDir;
      public Thread imageLoaderThread = new Thread() ;
      public ImageQueue imageQueue  = new ImageQueue();
      public ImageManager(Context context) {
        // Make background thread low priority, to avoid affecting UI performance
         imageLoaderThread.setPriority(Thread.NORM_PRIORITY-1);

        // Find the dir to save cached images
        String sdState = android.os.Environment.getExternalStorageState();
        if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
          File sdDir = android.os.Environment.getExternalStorageDirectory();    
          cacheDir = new File(sdDir,"data/codehenge");
        }
        else
          cacheDir = context.getCacheDir();

        if(!cacheDir.exists())
          cacheDir.mkdirs();
      }


      private void queueImage(String url, ImageView imageView) {
          // This ImageView might have been used for other images, so we clear 
          // the queue of old tasks before starting.
          imageQueue.Clean(imageView);
          ImageRef p=new ImageRef(url, imageView);

          synchronized(imageQueue.imageRefs) {
            imageQueue.imageRefs.push(p);
            imageQueue.imageRefs.notifyAll();
          }

          // Start thread if it's not started yet
          if(imageLoaderThread.getState() == Thread.State.NEW)
            imageLoaderThread.start();
        }




    private class ImageRef {
          public String url;
          public ImageView imageView;

          public ImageRef(String u, ImageView i) {
            url=u;
            imageView=i;
          }
        }

    private class ImageQueue {
          private Stack&lt;ImageRef&gt; imageRefs = new Stack&lt;ImageRef&gt;();

          //removes all instances of this ImageView
          public void Clean(ImageView view) {
            for(int i = 0 ;i &lt; imageRefs.size();) {
              if(imageRefs.get(i).imageView == view)
                imageRefs.remove(i);
              else ++i;
            }
          }
    }

    private class ImageQueueManager implements Runnable {
          @Override
          public void run() {
            try {
              while(true) {
                // Thread waits until there are images in the 
                // queue to be retrieved
                if(imageQueue.imageRefs.size() == 0) {
                  synchronized(imageQueue.imageRefs) {
                    imageQueue.imageRefs.wait();
                  }
                }

                // When we have images to be loaded
                if(imageQueue.imageRefs.size() != 0) {
                  ImageRef imageToLoad;

                  synchronized(imageQueue.imageRefs) {
                    imageToLoad = imageQueue.imageRefs.pop();
                  }

                  Bitmap bmp = getBitmap(imageToLoad.url);
                  imageMap.put(imageToLoad.url, bmp);
                  Object tag = imageToLoad.imageView.getTag();

                  // Make sure we have the right view - thread safety defender
                  if(tag != null &amp;&amp; ((String)tag).equals(imageToLoad.url)) {
                    BitmapDisplayer bmpDisplayer = 
                      new BitmapDisplayer(bmp, imageToLoad.imageView);

                    Activity a = 
                      (Activity)imageToLoad.imageView.getContext();

                    a.runOnUiThread(bmpDisplayer);
                  }
                }

                if(Thread.interrupted())
                  break;
              }


            }
             catch (InterruptedException e) {}
          }



private Bitmap getBitmap(String url) {
      String filename = String.valueOf(url.hashCode());
      File f = new File(cacheDir, filename);

      // Is the bitmap in our cache?
      Bitmap bitmap = BitmapFactory.decodeFile(f.getPath());
      if(bitmap != null) return bitmap;

      // Nope, have to download it
      try {
        bitmap = 
        BitmapFactory.decodeStream(new URL(url).openConnection().getInputStream());
        // save bitmap to cache for later
        writeFile(bitmap, f);

        return bitmap;
      } catch (Exception ex) {
        ex.printStackTrace();
        return null;
      }
    }

    private void writeFile(Bitmap bmp, File f) {
      FileOutputStream out = null;

      try {
        out = new FileOutputStream(f);
        bmp.compress(Bitmap.CompressFormat.PNG, 80, out);
      } catch (Exception e) {
        e.printStackTrace();
      }
      finally { 
        try { if (out != null ) out.close(); }
        catch(Exception ex) {} 
      }
    }
}

    public void displayImage(String url, Activity activity, ImageView imageView) {


        if(imageMap.containsKey(url)) {

            Bitmap bitmapToShow = imageMap.get(url);

            if(bitmapToShow != null) {
            //&gt; Image was cached well
            imageView.setImageBitmap(bitmapToShow);
            return;
            }
            }

            //&gt; Image was cached failed
        else {
            imageView.setImageResource(R.drawable.btn_radio);
            queueImage(url,imageView);
            return;
            }



        }

    private class BitmapDisplayer implements Runnable {
          Bitmap bitmap;
          ImageView imageView;

          public BitmapDisplayer(Bitmap b, ImageView i) {
            bitmap=b;
            imageView=i;
          }

          public void run() {
            if(bitmap != null)
              imageView.setImageBitmap(bitmap);
            else
              imageView.setImageResource(R.drawable.spinner_background);
          }
        }


}
</code></pre>

<p>My View:</p>

<pre><code>if( v == null){
        LayoutInflater li = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = li.inflate(R.layout.list_item,null);
        holder = new ViewHolder();

    holder.name = (TextView)v.findViewById(R.id.name);
    holder.text = (TextView)v.findViewById(R.id.text);
    holder.displayPic = (ImageView)v.findViewById(R.id.DisplayPicture);
    v.setTag(holder);

    }

    else
    {
        holder = (ViewHolder)v.getTag();

        obj = objs.get(position);
        if (obj != null)
        {
            holder.name.setText(obj.Name);
            holder.text.setText(""+obj.snippet);
            holder.displayPic.setTag(obj.ImageUrl);
            imageManager.displayImage(obj.ImageUrl, activity, holder.displayPic);

        }
}
</code></pre>
