Caching Android Images by Least Recently Used Algorithm
LinkedHashMap is created for easy least recently used data structures. You can store images, get and put by using this data structure easily.
But before using this data structure you should extend this class and overwrite some methods.
First you should use LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) constructor not the default one. And set accessOrder variable to true for LRU algorithm. Then you should overwrite removeEldestEntry method to remove least recently used object. This method is called before putting into hashmap, if map size is greated than cache size, then removeEldestEntry method is called. (You can look at javadoc if you are curios about LinkedHashMap, it helped me a lot)
At last you I am overwriting remove method, then unbinding drawable object to be sure that there won't be a reference that will cause memory leak and then recycle the bitmap. You should be carefull as you are forcing to recycle a bitmap, if it is in use on screen than it will cause an error. So implementing remove method is up to you. I would recommend that, if you are not getting an out of memory error, then do not overwrite remove method and do not unbind your drawable objects.
I am using a SoftReference to be sure that if memory is getting bigger and bigger Dalvik garbage collection will take care of these drawable objects. And getting a memory leak error would be much harder.
You can see full implementation of this class below.
import java.lang.ref.SoftReference;
import java.util.LinkedHashMap;
import java.util.Map;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
class LruCacheLinkedHashMap extends LinkedHashMap {
private final int maxEntries;
public LruCacheLinkedHashMap(final int maxEntries) {
super(maxEntries + 1, 1.0f, true);
this.maxEntries = maxEntries;
}
@Override
protected boolean removeEldestEntry(final Map.Entry eldest) {
return super.size() > maxEntries;
}
@Override
public Object remove(java.lang.Object key)
{
SoftReference softReferanceDrawable = (SoftReference) get(key);
unBindDrawable(softReferanceDrawable.get());
return super.remove(key);
}
private void unBindDrawable(Drawable drawable)
{
if(drawable != null)
{
drawable.setCallback(null);
if(!((BitmapDrawable)drawable).getBitmap().isRecycled())
{
((BitmapDrawable)drawable).getBitmap().recycle();
}
drawable = null;
}
}
}
You can create your LruCacheLinkedHashMap object in your java class.
static int CACHE_SIZE = YOUR_CACHE_SIZE_HERE; static Map> drawableHashMap = Collections.synchronizedMap(new LruCacheLinkedHashMap>(CACHE_SIZE));
And then you can put your drawable object into that data structure.
SoftReference softReferenceDrawable = new SoftReference(YOUR_DRAWABLE_OBJECT_HERE); drawableHashMap.put(YOUR_KEY_HERE, softReferenceDrawable);
You do not need to worry about removing objects, this class will take care of this stuff. Just put your drawable object into that hashmap.
Have a nice day!




