title: How to load images effectively and efficiently on scrolling in android
body: <p>Hello <code>stackoverflow</code> I'm trying to develop an application like <code>Gallery</code> for a particular directory of <code>SD Card</code>. For example I have took <code>WhatsApp Images</code> directory, here is my code</p>
  
  <pre><code>public class WhatsAppInboxImagesActivity extends Activity {
  
  private ImageAdapter imageAdapter;
  private ProgressDialog pd;
  ArrayList&lt;String&gt; f = null;
  File[] listFile;
  Button btnDelete;
  HashSet&lt;String&gt; selectedFile = null;
  GridView imagegrid;
  AlertDialog alertDialog = null;
  
  static
  {
      File noFile = new File(Environment.getExternalStorageDirectory().getPath(), "/WhatsApp/Media/WhatsApp Images/Sent/.nomedia");
      if(noFile.exists())
      {
          noFile.delete();
      }
  }//End of static block
  
  private void initialize()
  {
      imagegrid = (GridView) findViewById(R.id.PhoneImageGrid);
      btnDelete = (Button) findViewById(R.id.btnDeleteImg);
      selectedFile = new HashSet&lt;String&gt;();// list of file paths boolean checked
      f = new ArrayList&lt;String&gt;();// list of file paths
  }//End of initialize method
  
  @Override
  public void onCreate(Bundle savedInstanceState) 
  {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_whats_app_images_inbox);
  
      this.initialize();
      getFromSdcard();        
      imageAdapter = new ImageAdapter();
  
      /*
       * Performing time consuming actions
       */
      new AsyncTask&lt;Void, Void, Void&gt;() 
      {
          @Override
          protected void onPreExecute() 
          {
              pd = ProgressDialog.show(WhatsAppInboxImagesActivity.this,
                      "Loading..", "Please Wait", true, false);
          }// End of onPreExecute method
  
          @Override
          protected Void doInBackground(Void... params) 
          {
              return null;
          }// End of doInBackground method
  
          @Override
          protected void onPostExecute(Void result) 
          {
              imagegrid.setAdapter(imageAdapter);
              imageAdapter.notifyDataSetChanged();
              pd.dismiss();
          }
      }.execute((Void[]) null);
  
  
      btnDelete.setOnClickListener(new View.OnClickListener() 
      {
          @Override
          public void onClick(View v) 
          {
               new AsyncTask&lt;Void, Void, Void&gt;() 
               {
                      @Override
                      protected void onPreExecute() 
                      {
                          pd = ProgressDialog.show(WhatsAppInboxImagesActivity.this,
                                  "Loading..", "Please Wait", true, false);
                      }// End of onPreExecute method
  
                      @Override
                      protected Void doInBackground(Void... params) 
                      {
                          @SuppressWarnings("rawtypes")
                          Iterator iterator = selectedFile.iterator();
                          while (iterator.hasNext())
                          {
                              new File(iterator.next().toString()).delete();
                          }//End of while loop
                          return null;
                      }// End of doInBackground method
  
                      @Override
                      protected void onPostExecute(Void result) 
                      {
                          pd.dismiss();
                      }//End of onPostExecute method
                  }.execute((Void[]) null);
  
                  finish();
                  startActivity(getIntent());
          }//End of onClick method
      });//End of btnDelete anonymous class
  
  }//End of onCreate method
  
  public void getFromSdcard() 
  {
      File file = new File( Environment.getExternalStorageDirectory().getPath(), "/WhatsApp/Media/WhatsApp Images");
  
      if (file.isDirectory()) 
      {
          listFile = file.listFiles();
          for (int i = 0; i &lt; listFile.length; i++) 
          {
              if(listFile[i].isDirectory())
              {
                  continue;
              }
              f.add(listFile[i].getAbsolutePath());
          }//End of for loop
      }//End of if condition
  }//End of getFromSdcard method
  
  public class ImageAdapter extends BaseAdapter 
  {
      private LayoutInflater mInflater;
  
      public ImageAdapter() 
      {
          mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      }//End of ImageAdapter constructor
  
      public int getCount() 
      {
          return f.size();
      }//End of getCount method
  
      public Object getItem(int position) 
      {
          return position;
      }//End of getItem method
  
      public long getItemId(int position) 
      {
          return position;
      }//End of getItemId method
  
      public View getView(int position, View convertView, ViewGroup parent) 
      {
          ViewHolder holder;
          if (convertView == null) 
          {
              holder = new ViewHolder();
              convertView = mInflater.inflate(R.layout.galleryitem, null);
              holder.imageview = (ImageView) convertView.findViewById(R.id.thumbImage);
              holder.checkbox = (CheckBox) convertView.findViewById(R.id.itemCheckBox);
  
              convertView.setTag(holder);
          }//End of if condition
          else 
          {
              holder = (ViewHolder) convertView.getTag();
          }//End of else
  
          BitmapFactory.Options options = new BitmapFactory.Options();
          // will results in a much smaller image than the original
          options.inSampleSize = 4;
  
          // don't ever use a path to /sdcard like this, but I'm sure you have a sane way to do that
          // in this case nebulae.jpg is a 19MB 8000x3874px image
          final Bitmap b = BitmapFactory.decodeFile(f.get(position), options);
  
          holder.imageview.setImageBitmap(b);
  
          return convertView;
      }//End of getView method
  }//End of ImageAdapter instance inner class
  
  class ViewHolder 
  {
      ImageView imageview;
      CheckBox checkbox;
      int id;
  }//End of ViewHolder instance inner class
  }//End of WhatsAppImagesActivity
  </code></pre>
  
  <p>So far every thing is good, but the problem is images gets loaded all at <code>one shot</code>, so scrolling is very slow and some times <code>OutOfMemoryException</code> occurs though <code>decoded</code> file with <code>BitMapFactory</code>, can any one help me to solve this puzzle please.</p>
  
  <p>Edit:</p>
  
  <pre><code>@Override
  public View getView(int position, View convertView, ViewGroup parent) {
      View view = null;
      if (convertView == null) {
          LayoutInflater inflator = context.getLayoutInflater();
          view = inflator.inflate(R.layout.list_layout, null);
          final ViewHolder viewHolder = new ViewHolder();
          viewHolder.text = (TextView) view.findViewById(R.id.label);
          viewHolder.text.setTextColor(Color.BLACK);
          viewHolder.image = (ImageView) view.findViewById(R.id.image);
          viewHolder.image.setVisibility(View.GONE);
          viewHolder.cb = (CheckBox) view.findViewById(R.id.item_check_box);
          viewHolder.pb = (ProgressBar) view.findViewById(R.id.progressBar);
          view.setTag(viewHolder);
      } else {
          view = convertView;
      }
      final int pos = position;
      ViewHolder holder = (ViewHolder) view.getTag();
      holder.text.setText(list.get(position).getName());
      holder.image.setTag(list.get(position).getURL());
      holder.image.setId(position);
      PbAndImage pb_and_image = new PbAndImage();
      pb_and_image.setImg(holder.image);
      pb_and_image.setPb(holder.pb);
      new DownloadImageTask().execute(pb_and_image);
      return view;
  }
  </code></pre>
  
  <p>Thanks.</p>