Search code examples
androidandroid-lru-cache

Out of memory with LruCache?


In last line I get a crash:

InputStream in = new BufferedInputStream(new FileInputStream(file));
byte[] buf = new byte[(int) file.length()];
int numRead = in.read(buf);
final Bitmap bitmap = BitmapFactory.decodeByteArray(buf, 0, numRead); <--- crash

How to avoid it?

E/dalvikvm-heap: Out of memory on a 31961104-byte allocation.

Am I understand good that 31MB is the limit to use memory? Using LRUCache to store images. I set 60MB to store data. Is it too much?

public static int cacheSize = 60 * 1024 * 1024; // 4MiB
    public static LruCache<String, Bitmap> images = new LruCache<String, Bitmap>(cacheSize) {
        protected int sizeOf(String key, Bitmap value) {
            return value.getByteCount();
        }
    };

In my case an image is around 3MB, and at least 18 image I need to store in cache. Is it so big demand from a phone to store 60MB?

I have a try catch around code, why app terminates?


Solution

  • How to avoid it?

    Well, you could help your cause by using decodeStream() instead of decodeByteArray(). As it stands, you are pointlessly wasting heap space by reading in the entire encoded image before decoding it.

    However, in general, your problem has nothing to do with the LRUCache, and everything to do with trying to make large (~30MB) allocations. 31961104 bytes, as a Bitmap, is equivalent to a 2826px by 2826px image. That is much larger than most Android screens. You may not have a single contiguous block of heap space for one of those, let alone 18. 18 might take up more memory than the entire device has, for low-end Android devices.

    Am I understand good that 31MB is the limit to use memory?

    No. The error indicates that you do not have a single block of free memory that is sufficient for that image.

    In my case an image is around 3MB

    Perhaps on disk it is. Most image file formats are compressed (PNG, JPEG, WebP, GIF etc.). The amount of heap space that you use is based on the decompressed size. As njzk3 notes, the heap space is based on resolution (width x height, in pixels) and bit depth (4 bytes per pixel by default).

    What can I do?

    Use a smaller bitmap.

    Or, do not load the entire bitmap into memory, but instead use widgets that can progressively load the image as needed based on user pan and zoom gestures.