Java.lang.OutOfMemoryError: bitmap size exceeds VM budget in ListView and lazy image loading

I have a listview that probably has infinite elements that load endlessly endlessly.

Each list item has one or two images that I lazily upload.

Everything works fine, but when I scroll it for a very long time, it crashes with this in log cat

 08-07 15:26:25.231: E/AndroidRuntime(30979): FATAL EXCEPTION: Thread-60
08-07 15:26:25.231: E/AndroidRuntime(30979): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
08-07 15:26:25.231: E/AndroidRuntime(30979):    at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
08-07 15:26:25.231: E/AndroidRuntime(30979):    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
08-07 15:26:25.231: E/AndroidRuntime(30979):    at com.test.android.helper.LazyImageLoader.decodeFile(LazyImageLoader.java:171)
08-07 15:26:25.231: E/AndroidRuntime(30979):    at com.test.android.helper.LazyImageLoader.getBitmap(LazyImageLoader.java:112)
08-07 15:26:25.231: E/AndroidRuntime(30979):    at com.test.android.helper.LazyImageLoader.access$2(LazyImageLoader.java:106)
08-07 15:26:25.231: E/AndroidRuntime(30979):    at com.test.android.helper.LazyImageLoader$ImageLoader.run(LazyImageLoader.java:197)

In my lazy image downloader, I store bitmaps in WeakHashMap. So, should the garbage collector properly collect bitmaps?

My lazy image downloader works something like this.

I am calling displayImage()from my adapter with url and link to imageview

public void displayImage(String url, ImageView imageView, int defaultImageResourceId){

        latestImageMetaData.put(imageView, url);

        if(weakhashmapcache.containsKey(url)){
            imageView.setImageBitmap(weakhashmapcache.get(url));
        }
        else{
            enqueueImage(url, imageView, defaultImageResourceId);
            imageView.setImageResource(defaultImageResourceId);
        }
    }

, , , enqueueImage().

private void enqueueImage (String url, ImageView imageView, int defaultImageResourceId) {       Image image = new (url, imageView, defaultImageResourceId);       downloadqueue.add();       //downloadQueue - ,       // , , ,        = downloadQueue.iterator();       while (iterator.hasNext() && downloadQueue.remainingCapacity() < 80) {           downloadQueue.remove(iterator.next());       }   }

And my image loader thread is this - 

class ImageLoader extends Thread {

    public void run() {
        Image firstImageInQueue;

        try {
            while((firstImageInQueue = downloadQueue.take()) != SHUTDOWN_TOKEN)
            {
                Bitmap imageBitmap = getBitmap(firstImageInQueue.url);

                if(imageBitmap != null){
                    weakhashmap.put(firstImageInQueue.url, imageBitmap);
                    BitmapDisplayer displayer = new BitmapDisplayer(imageBitmap, firstImageInQueue.imageView, firstImageInQueue.url, firstImageInQueue.defaultImageResourceId);
                    Activity activity = (Activity)firstImageInQueue.imageView.getContext();
                    activity.runOnUiThread(displayer);
                }
            }
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        finally {
            imageLoaderTerminated = true;
        }
    } 
}

getBitmap() url Bitmap. BitmapDisplayer - Runnable, .

?

+5
2

, , .

. . , , , ,

int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)) .getMemoryClass();

LruCache WeakHashMap. LruCache . WeakHashMap LruCache. Android .

Jake Wharton DiskLruCache - Disk Cache.

, . , , .

BitmapFactory.Options, .

, - , .

+1

, , . , .

!!

+1

All Articles