xXJJJasonMokXx
xXJJJasonMokXx

Reputation: 367

Android: LruCache does not work

I followed the link on developer.android.com and created the following code:

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

    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {

        @Override
        protected int sizeOf(String key, Bitmap value) {
            return super.sizeOf(key, value);
        }
    };

    if(getBitmapFromCache(sBitmapCacheKey) == null) {
        Log.e(LOG_TAG, "No image cached");
        applyBlur();
    }else{
        Log.e(LOG_TAG, "Found image cached, applying");
        setBackgroundFromCache();
    }

method applyBlur()

    private void applyBlur() {
    Log.e(LOG_TAG, "applying blur");
    blur(convert(WallpaperManager.getInstance(this).getDrawable()), null);
}

private void blur(Bitmap bitmap, View view) {
    long start = System.currentTimeMillis();
    float radius = 25;

    ...          

    addBitmapToCache(sBitmapCacheKey, overlay);

    rs.destroy();
    Log.e(LOG_TAG, "It took: " + (System.currentTimeMillis() - start) + "ms");
}

Where applyBlur() is a method I use to create the Bitamp and add to LruCache.

From the Logcat it always says "No image cached" and will create a whole new Bitmap

I am quite a newbie so I haven't used cache before, any ideas would be greatly appreciated, thanks.

Upvotes: 0

Views: 727

Answers (1)

Carl Anderson
Carl Anderson

Reputation: 3476

Your cache isn't working is for a couple of reasons. As discussed already, you need to have matching size functions, first of all. You can't initialize the cache to a memory size and then use image count in the sizeOf function (or vice versa). If you want to use image size, you need to change your sizeOf function to something like this:

@Override
protected int sizeOf(final String key, final Bitmap value) {
    return value.getRowBytes() * value.getHeight();
}

Secondly, you need to have a better grasp of how the cache is used, and how the Activity lifecycle works. Creating and storing this in an Activity isn't going to work, because an Activity can potentially be destroyed by the Android operating system at any moment, which will cause your Cache to be garbage-collected (removed from memory). One way to avoid this is to create a new class that extends LruCache, and then have a singleton getter function that initializes the cache, and is available for anyone to use. Here's an example:

public final class Example extends LruCache<String, Bitmap> {

    private static Example instance;

    private Example(final int maxSize) {
        super(maxSize);
    }

    public static Example get() {
        if (instance == null) {
            final int cacheSize = (int) (Runtime.getRuntime().maxMemory()) / 1024;
            instance = new Example(cacheSize);
        }
        return instance;
    }

    @Override
    protected int sizeOf(final String key, final Bitmap value) {
        return value.getRowBytes() * value.getHeight();
    }

}

In order to use this in your Activity, you simply call Example.get(), and that will consistently give you the same cache every time, across all of your activities, ensuring that if you store a Bitmap in one Activity, that it's available for any other Activity too.

Upvotes: 2

Related Questions