问题
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.
回答1:
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
回答2:
You can also recycle bitmaps that pops out from lrucache
final Bitmap bmp = mLruCache.put(key, data);
if (bmp != null)
bmp.recycle();
回答3:
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.
来源:https://stackoverflow.com/questions/15459834/lrucache-not-working