7
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    final int cacheSize = maxMemory / 8;
    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                // The cache size will be measured in kilobytes rather than
                // number of items.
                return bitmap.getByteCount() / 1024;
            }
        };
    URL url = new URL("http://s2.goodfon.ru/image/260463-1920x1200.jpg");
    Bitmap bitmap = BitmapFactory.decodeStream((InputStream) url.getContent(), null, options);
    if(bitmap != null)
        Log.i("Success", "BITMAP IS NOT NULL");

    String key = "myKey";
    Log.i("Get is null", "putting myKey");
    mMemoryCache.put(key, bitmap);

    Bitmap newBitmap = mMemoryCache.get(key);
    if(newBitmap == null)
        Log.i("newBitmap", "is null");

Hello, here is a code. I get bitmap from URL successfully (Log says Bitmap is not null and I can display it easy). Then I am trying to put it into LruCache and get it back, but it return null. (Log says newBitmap is null). Where is my mistake? Please, tell me. Android 4.1.2 Cache size 8192 Kb.

Faceles
  • 453
  • 1
  • 5
  • 16
  • So, have you tried, that your calculation for the cache size is correct? And what does `sizeOf()` output? Are you sure the image is really inside the cache? – ConcurrentHashMap Mar 17 '13 at 10:46
  • http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html. – Raghunandan Mar 17 '13 at 10:56
  • Oh that image was 9000 kb, I thought its 1.19 mb as a file. Problem solved. Thank you. Plaese tell me, why 1.19 mb file returns 9000 kb in getByteCount / 1024? – Faceles Mar 17 '13 at 11:06

3 Answers3

8

If it is 1.19 MB on disk but ~ 9 MB in memory, that means that as a compressed JPEG file, it's 1.19 MB and once you extract that into a Bitmap (uncompressed) that can be displayed, it will take up 9 MB in memory. If it's a 1920 x 1200 pixel image as suggested by the url in your code snippet, the image will take up 1920 x 1200 x 4 bytes of memory (4 bytes for each pixel to represent ARGB values from 0 to 256 times 2.3 million total pixels = 9,216,000 bytes). If you're using 1/8 of your available memory for this cache, it's possible/likely that 9MB exceeds that total memory space so the Bitmap never makes it into the cache or is evicted immediately.

You're probably going to want to downsample the image at decoding time if it's that large (using BitmapFactory.Options.inSampleSize...lot's of documentation on the web for using that if you're not already familiar).

Also, you're using Runtime.maxMemory to compute your cache size. This means you're requesting the maximum amount of memory that the whole VM is allowed to use.

http://developer.android.com/reference/java/lang/Runtime.html#maxMemory%28%29

The more common approach is the use the value given back to you by the ActivityManager.getMemoryClass() method.

Here's an example code snippet and the method definition in the docs for reference.

    ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    int memClassBytes = am.getMemoryClass() * 1024 * 1024;
    int cacheSize = memClassBytes / 8;
    mMemoryCache = new LruCache<String, Bitmap>(cacheSize)

http://developer.android.com/reference/android/app/ActivityManager.html#getMemoryClass%28%29

Rich
  • 36,270
  • 31
  • 115
  • 154
  • If i were a Football Commentator : Rich Strikes again , solid Goal , Dalvik has no chance to stop this Code , what a of this beautiful evening ! – Tushar Pandey Jul 06 '13 at 10:45
0

You can also recycle bitmaps that pops out from lrucache

final Bitmap bmp = mLruCache.put(key, data);
if (bmp != null)
    bmp.recycle();
Kalyaganov Alexey
  • 1,701
  • 1
  • 16
  • 23
0

The Android example was wrong when dividing Runtime maxMemory by 1024 in the following line:

final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

The unit of the maxMemory is Byte which is the same with the 'cacheSize' ('/ 8' just means it will use eighth of the available memory of the current Activity). Therefore, '/ 1024' will make the 'cacheSize' extremely small such that no bitmap can be actually 'cached' in 'mMemoryCache'.

The solution will be delete '/ 1024' in the above code.

James
  • 320
  • 2
  • 8