title: ListView scrolling lag in android
body: <p>I have a customized list view in my application, which is showing an image and text (Json). The image I am getting from URL is working, but listview is laggy (scrolling lag).
  Maybe my problem is ImageLoader.java class
  This is my code:</p>
  
  <pre><code>public class ImageLoader {
  MemoryCache memoryCache = new MemoryCache();
  FileCache fileCache;
  private Map&lt;ImageView, String&gt; imageViews = Collections
          .synchronizedMap(new WeakHashMap&lt;ImageView, String&gt;());
  ExecutorService executorService;
  
  public ImageLoader(Context context) {
      fileCache = new FileCache(context);
      executorService = Executors.newFixedThreadPool(5);
  }
  
  final int stub_id = R.drawable.aaaaaaaaaaaaaaa;
  
  public void DisplayImage(String url, ImageView imageView) {
      imageViews.put(imageView, url);
      Bitmap bitmap = memoryCache.get(url);
      if (bitmap != null)
          imageView.setImageBitmap(bitmap);
      else {
          queuePhoto(url, imageView);
          imageView.setImageResource(stub_id);
      }
  }
  
  private void queuePhoto(String url, ImageView imageView) {
      PhotoToLoad p = new PhotoToLoad(url, imageView);
      executorService.submit(new PhotosLoader(p));
  }
  
  private Bitmap getBitmap(String url) {
      File f = fileCache.getFile(url);
  
      // from SD cache
      Bitmap b = decodeFile(f);
      if (b != null)
          return b;
  
      // from web
      try {
          Bitmap bitmap = null;
          URL imageUrl = new URL(url);
          HttpURLConnection conn = (HttpURLConnection) imageUrl
                  .openConnection();
          conn.setConnectTimeout(30000);
          conn.setReadTimeout(30000);
          conn.setInstanceFollowRedirects(true);
          InputStream is = conn.getInputStream();
          OutputStream os = new FileOutputStream(f);
          Utils.CopyStream(is, os);
          os.close();
          bitmap = decodeFile(f);
          return bitmap;
      } catch (Throwable ex) {
          ex.printStackTrace();
          if (ex instanceof OutOfMemoryError)
              memoryCache.clear();
          return null;
      }
  }
  
  // decodes image and scales it to reduce memory consumption
  private Bitmap decodeFile(File f) {
      try {
          // decode image size
          BitmapFactory.Options o = new BitmapFactory.Options();
          o.inJustDecodeBounds = true;
          FileInputStream stream1 = new FileInputStream(f);
          BitmapFactory.decodeStream(stream1, null, o);
          stream1.close();
  
          // Find the correct scale value. It should be the power of 2.
          final int REQUIRED_SIZE = 70;
          int width_tmp = o.outWidth, height_tmp = o.outHeight;
          int scale = 1;
          while (true) {
              if (width_tmp / 2 &lt; REQUIRED_SIZE
                      || height_tmp / 2 &lt; REQUIRED_SIZE)
                  break;
              width_tmp /= 2;
              height_tmp /= 2;
              scale *= 2;
          }
  
          // decode with inSampleSize
          BitmapFactory.Options o2 = new BitmapFactory.Options();
          o2.inSampleSize = scale;
          FileInputStream stream2 = new FileInputStream(f);
          Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2);
          stream2.close();
          return bitmap;
      } catch (FileNotFoundException e) {
      } catch (IOException e) {
          e.printStackTrace();
      }
      return null;
  }
  
  // Task for the queue
  private class PhotoToLoad {
      public String url;
      public ImageView imageView;
  
      public PhotoToLoad(String u, ImageView i) {
          url = u;
          imageView = i;
      }
  }
  
  class PhotosLoader implements Runnable {
      PhotoToLoad photoToLoad;
  
      PhotosLoader(PhotoToLoad photoToLoad) {
          this.photoToLoad = photoToLoad;
      }
  
      @Override
      public void run() {
          try {
              if (imageViewReused(photoToLoad))
                  return;
              Bitmap bmp = getBitmap(photoToLoad.url);
              memoryCache.put(photoToLoad.url, bmp);
              if (imageViewReused(photoToLoad))
                  return;
              BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);
              Activity a = (Activity) photoToLoad.imageView.getContext();
              a.runOnUiThread(bd);
          } catch (Throwable th) {
              th.printStackTrace();
          }
      }
  }
  
  boolean imageViewReused(PhotoToLoad photoToLoad) {
      String tag = imageViews.get(photoToLoad.imageView);
      if (tag == null || !tag.equals(photoToLoad.url))
          return true;
      return false;
  }
  
  // Used to display bitmap in the UI thread
  class BitmapDisplayer implements Runnable {
      Bitmap bitmap;
      PhotoToLoad photoToLoad;
  
      public BitmapDisplayer(Bitmap b, PhotoToLoad p) {
          bitmap = b;
          photoToLoad = p;
      }
  
      public void run() {
          if (imageViewReused(photoToLoad))
              return;
          if (bitmap != null)
              photoToLoad.imageView.setImageBitmap(bitmap);
          else
              photoToLoad.imageView.setImageResource(stub_id);
      }
  }
  
  public void clearCache() {
      memoryCache.clear();
      fileCache.clear();
  }
  
  }
  </code></pre>
  
  <p>This is a also my BaseAdapter.java class</p>
  
  <pre><code>public class BRIgeAdapter extends BaseAdapter {
  private LayoutInflater inflater;
  private Activity activity;
  public ArrayList&lt;HashMap&lt;String, String&gt;&gt; data;
  public ViewHolder holder;
  public ImageLoader imageLoader;
  HashMap&lt;String, String&gt; itemList;
  private int screenSize;
  MainActivity main;
  public BRIgeAdapter(Activity a, ArrayList&lt;HashMap&lt;String, String&gt;&gt; d,int screenSize) {
      this.activity = a;
      this.data = d;
      this.screenSize = screenSize;
      inflater = (LayoutInflater) activity
              .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      imageLoader = new ImageLoader(activity.getApplicationContext());
  }
  public int getCount() {
      return data.size();
  }
  public Object getItem(int position) {
      return data.get(position);
  }
  public long getItemId(int position) {
      return (long) position;
  }
  @Override
  public int getViewTypeCount() {
      return data.size();
  }
  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
      if (convertView == null) {
          holder = new ViewHolder();
          main = new MainActivity();
          convertView = inflater.inflate(R.layout.list_row, parent, false);
  
          holder.journal = (TextView) convertView
                  .findViewById(R.id.smalljournal);
          holder.statId = (TextView) convertView
                  .findViewById(R.id.smallstatID);
  
          holder.smallDescription1 = (TextView) convertView
          .findViewById(R.id.smallDescription1);
          holder.DateTime = (TextView) convertView
                  .findViewById(R.id.smallDateTime);
          holder.thumb_image = (ImageView) convertView
                  .findViewById(R.id.smallthumb);
          holder.title = (TextView) convertView.findViewById(R.id.smalltitle);
          holder.description = (TextView) convertView
                  .findViewById(R.id.smallDescription);
          convertView.setTag(holder);
      } else {
          holder = (ViewHolder) convertView.getTag();
      }
      itemList = data.get(position);
      if (itemList != null) {
          holder.journal.setText(itemList.get(MainActivity.KEY_journal));
          // holder.DateTime.setText(itemList.get(MainActivity.KEY_pubDate));
          holder.statId.setText(itemList.get(MainActivity.KEY_statID));
          holder.smallDescription1.setText(itemList.get(MainActivity.KEY_description));
          holder.journal.setTypeface(MainActivity.tf2);
          String titleString = itemList.get(MainActivity.KEY_title);
          Calendar cal = new GregorianCalendar(2013, 11, 20);
          DateFormat df = new SimpleDateFormat("dd.MM.yyyy");
          // DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
          String date = df.format(cal.getTime());
          String DateTime = itemList.get(MainActivity.KEY_pubDate);
          DateTime = date;
          holder.DateTime.setText(DateTime);
          holder.title.setText(titleString);
          holder.title.setTypeface(MainActivity.tf2);
  
          holder.title.setLineSpacing(2, 1.2f);
          holder.description.setLineSpacing(2, 1.2f);
  
          if(screenSize == Configuration.SCREENLAYOUT_SIZE_NORMAL)
              holder.description.setVisibility(View.INVISIBLE);
          else
              holder.description.setText(itemList.get(MainActivity.KEY_description));
  
          holder.description.setTypeface(MainActivity.tf2);
          imageLoader.DisplayImage(itemList.get(MainActivity.KEY_image),
                  holder.thumb_image);
      }
      return convertView;
  }
  static class ViewHolder {
      public TextView journal, title, description,smallDescription1, DateTime, statId;
      ImageView thumb_image;
  }
   }
  </code></pre>
  
  <p>Is there any possible way I can reduce or remove this lagging?</p>