title: Why are wrong images getting loaded in ListView occasionally?
body: <p>I have a listview which loads images in every cell in async. When I try to scroll down slowly(after all the images in the current view are loaded), it works flawlessly. 
  But when I try to scroll down before they are even loaded and scroll up, I face this issue. The cells start to show up images which don't correspond to them.</p>
  
  <p>My getView method looks like this:</p>
  
  <pre><code>public View getView(final int position, View convertView, ViewGroup parent) {
  
      // TODO Auto-generated method stub
  
      View rowView = null;
  
      if(convertView == null) {
          rowView = inflater.inflate(R.layout.list_posts_item, null);
          final Holder holder=new Holder();
          holder.tvTitle=(TextView) rowView.findViewById(R.id.tvTitleNamePost);
          holder.ivPrimaryImage=(ImageView) rowView.findViewById(R.id.ivPrimaryImage);
          holder.tvLocality=(TextView) rowView.findViewById(R.id.tvLocalityPosts);
          holder.tvDateCreated=(TextView) rowView.findViewById(R.id.tvDateCreated);
          rowView.setTag(holder);
      }else {
          rowView=convertView;
      }
  
      Holder holder = (Holder)rowView.getTag();
      holder.ivPrimaryImage.setId(position);
      holder.ivPrimaryImage.setTag(listOfPosts.get(position).getPostId());
      holder.ivPrimaryImage.setImageBitmap(null); // Added for flickering issue
      holder.tvTitle.setText(listOfPosts.get(position).getTitle());
      holder.tvLocality.setText(listOfPosts.get(position).getLocality());
      holder.tvDateCreated.setText(listOfPosts.get(position).getCreatedDate());
      postId = listOfPosts.get(position).getPostId();
      Image image = new Image();
      image.setImg(holder.ivPrimaryImage);
  
      if (!"N".equalsIgnoreCase(listOfPosts.get(position).getHasImage()) ) {
          if(!tagsCaching.containsKey(postId))
              new GetPrimaryImages().execute(image);
          else
               holder.ivPrimaryImage.setImageBitmap(tagsCaching.get(postId));
      }
  
      return rowView;
  }
  </code></pre>
  
  <p>And my Async call class looks like this:</p>
  
  <pre><code>public class GetPrimaryImages extends AsyncTask&lt;Image, Void, Bitmap&gt; {
  
  ImageView imageView = null;
      protected Bitmap doInBackground(Image... images) {
      this.imageView=images[0].getImg();
  
  
  
          // Building Parameters
          List&lt;NameValuePair&gt; params = new ArrayList&lt;NameValuePair&gt;();
          params.add(new BasicNameValuePair("postid",(String)(this.imageView.getTag()) ));
  
  
               json = jsonParser.makeHttpRequest(CommonResources.getURL("get_primary_image"),
                      "POST", params);
  
  
          if(json == null){
              return null;
          }
          Log.d("Fetching Image",imageView.getTag()+ json.toString());
          tagsDownloaded.add((String)imageView.getTag());
          // check for success tag
          String TAG_SUCCESS = "success";
          try {
              int success = json.getInt(TAG_SUCCESS);
  
              if (success == 0) {
                 image =  json.getString("primaryimage");
  
              }
          } catch (JSONException e) {
              e.printStackTrace();
          }
  
          return getImage(image);
  
      }
  
      /**
       * After completing background task Dismiss the progress dialog
       * **/
      protected void onPostExecute(Bitmap result) {
          tagsCaching.put((String)imageView.getTag(), result);
          imageView.setImageBitmap(result);
  
      }
  
      public Bitmap getImage(String imageString) {
          if("null".equalsIgnoreCase(imageString)){
              return null;
          }else{
              byte[] decodedString = Base64.decode(imageString, Base64.DEFAULT);
              Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
              //image.setImageBitmap(decodedByte);
              return decodedByte;
          }
  
      }
  
  
  }
  </code></pre>
  
  <p>Edit:</p>
  
  <p>I added a new instance variable to Holder:</p>
  
  <pre><code>public class Holder
  {
      TextView tvTitle;
      ImageView ivPrimaryImage;
      TextView tvLocality;
      TextView tvDateCreated;
      int position;
  }
  </code></pre>
  
  <p>Set the same in the getView:
      holder.position = position;
  And passed the holder object to the Async task:
      new GetPrimaryImages(position, holder).execute(image);</p>
  
  <p>And modified the Async call class as follows:
  1. Added cancel to the http call
  2. Changed the onPostExecute method</p>
  
  <pre><code>  public class GetPrimaryImages extends AsyncTask&lt;Image, Void, Bitmap&gt; {
  
      int mPosition;
      Holder mHolder;
      public GetPrimaryImages(int position, Holder holder){
          mPosition = position;
          mHolder = holder;
      }
  
      ImageView imageView = null;
      protected Bitmap doInBackground(Image... images) {
      this.imageView=images[0].getImg();
  
  
  
          List&lt;NameValuePair&gt; params = new ArrayList&lt;NameValuePair&gt;();
          params.add(new BasicNameValuePair("postid",(String)(this.imageView.getTag()) ));
  
  
          JSONObject json;
          if(mHolder.position == mPosition)
               json = jsonParser.makeHttpRequest(CommonResources.getURL("get_primary_image"),
                      "POST", params);
  
          else {
              json = null;
              cancel(true);
          }
  
          // check log cat fro response
          if(json == null){
              return null;
          }
          Log.d("Fetching Image",imageView.getTag()+ json.toString());
          tagsDownloaded.add((String)imageView.getTag());
          // check for success tag
          String TAG_SUCCESS = "success";
          try {
              int success = json.getInt(TAG_SUCCESS);
  
              if (success == 0) {
                 image =  json.getString("primaryimage");
  
              }
          } catch (JSONException e) {
              e.printStackTrace();
          }
  
          return getImage(image);
  
      }
  
  
      protected void onPostExecute(Bitmap result) {
          if (mHolder.position == mPosition) {
              tagsCaching.put((String) imageView.getTag(), result);
              imageView.setImageBitmap(result);
          }
  
      }
  
      public Bitmap getImage(String imageString) {
  
  
          //needs to wait
          if("null".equalsIgnoreCase(imageString)){
              return null;
          }else{
              byte[] decodedString = Base64.decode(imageString, Base64.DEFAULT);
              Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
              //image.setImageBitmap(decodedByte);
              return decodedByte;
          }
  
      }
  
  
  }
  </code></pre>
  
  <p>It seems to be working. :)</p>
  
  <p>Now my doubt is what would be the best way to cache the images? Should be writing it to a file? and reading it from it every time I scroll up?</p>