3

I have a ListView that displays images loaded from the SD (JPGs previously taken with the camera). I use imageView.setImageBitmap() because the images are too large to display in the list and consume too much (native) memory, so I load a subsampled version with inSampleSize.

My problem is that the scroll delays before a new row is going to be displayed. Depending on the device the delay is more or less. Once you have reached the end the list the scroll becomes fluid.

Originally I performed the bitmap decoding in the ListAdapter getView():

BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = 2; //Subsample the original image
bitmapOptions.inPurgeable = true; //The system can free the ¿native? memory allocated by the bitmap if needed
bitmapOptions.inInputShareable = true; //Works in conjuction with inPurgeable
bitmap = BitmapFactory.decodeFile(path, bitmapOptions);
imageView.setImageBitmap(bitmap);

Then I tried to perform the decoding outside the UI thread. I executed an AsyncTask to decode all the bitmaps and cache it in memory. So in the getView() I only did imageView.setImageBitmap(). But I saw the same delay when scrolling. Using the method profiling tool in the DDMS I saw that the method Canvas.native_drawBitmap() was causing the delay, so the problem was not the bitmap decoding, but the ImageView drawing.

¿Any ideas to workaround this? ¿Why once a row have been displayed the first time there is no more delay when displaying this row? Maybe there is an ImageView displaying cache.

Community
  • 1
  • 1
Juan T
  • 1,018
  • 11
  • 12

2 Answers2

3

When you are scrolling the list, its loading dynamically in the main thread. At that time you are trying to do setImageBitmap() which is in turn trying to do in main thread. So whole task is slowed down.

So the solution is so setImageBitmap() in a runOnUiThread(runnable) or Handler. I faced this problem. This is the solution.

EDIT :

Do this,

Handler handler = new Handler() {
   @Override    
   public void handleMessage(Message message) { 
        // do setImageBitmap(bitmap)    
   }    
};


new Thread() {  
   @Override    
   public void run() {  
        //get your bitmap   
        Message message = handler.obtainMessage(0, bitmap); 
        handler.sendMessage(message);   
   }
}.start();
Debarati
  • 3,296
  • 2
  • 18
  • 30
  • So the goal is to avoid running the scroll in parallel with the `setImageBitmap()`. ¿Do you mean putting the `setImageBitmap()` in a `handler.postDelayed()`? Beacuse `runOnUiThread()` and `handler.post()` runs inmediatly on the UI thread, I have tested it and the effect is the same. With `handler.postDelayed(runnable, 400)` I dont see the delay (testing on a Wildfire) when scrolling but on the other side the delay loading the image is a bit high. I will continue testing. – Juan T Aug 16 '12 at 11:17
0

When you scroll your view, getView() method of your list adapter is called. This means, the more work you load to this method, the more it will delay.