I have been trying to learn as much as possible about Android development with specific focus on performance since many apps in the Play store today are sluggish. I have found/been directed to many articles/videos.
One specific article about image caching is at: http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html
The author has code available at: http://code.google.com/p/android-imagedownloader/source/browse/trunk/src/com/example/android/imagedownloader/ImageDownloader.java
Which Google seemed to take a version of into and put into their sample classes at: http://developer.android.com/resources/samples/XmlAdapters/src/com/example/android/xmladapters/ImageDownloader.html
In general it is solid, except for what I think is a flaw in the caching. It uses a soft / hard cache that puts / gets things into the hard cache because the Android system resets the soft cache quite often.
Looking at the code though, one starts to wonder if the hard cache would get accidentally reset every time the parent class is instantiated.
First the soft cache:
// Soft cache for bitmaps kicked out of hard cache
private final static ConcurrentHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache =
new ConcurrentHashMap<String, SoftReference<Bitmap>>(HARD_CACHE_CAPACITY / 2);
Now take a look at the hard cache:
// Hard cache, with a fixed maximum capacity and a life duration
private final HashMap<String, Bitmap> sHardBitmapCache =
new LinkedHashMap<String, Bitmap>(HARD_CACHE_CAPACITY / 2, 0.75f, true) {
@Override
protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) {
if (size() > HARD_CACHE_CAPACITY) {
// Entries push-out of hard reference cache are transferred to soft reference cache
sSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
return true;
} else
return false;
}
};
The hard cache is not static, while the soft cache is static. So the hard cache instance and therefore items get cleared with the life of the instance of the class.
The reason I think this is true is that I noticed my application with a ListView/ImageView, was downloading the image every time and never caching it. It was all done asynchronously, but still hitting the net every time. I verified this by putting a Log.d()
statement inside my method that hits the web and seeing when/how often it was called.
Adding the static keyword fixed the issue and my application is much more performant.
I am not sure why this is the case as there is only one instance of the ImageDownloader class in my adapter as shown in the example:
private final ImageDownloader imageDownloader = new ImageDownloader();
THE QUESTION
With all of that said, has anyone else experienced this??? Or am I a combination of crazy/wrong somehow. I am no Java/Android/JVM/Dalvik/WeakReference/SoftReference expert, but something seems a bit off. I don't know why sHardBitmapCache
was not made static, but when I made the change my application stopped hitting the web so much (saving on data costs / battery drainage / performance improvements).
You are correct, this is a typo on my part.
I have fixed the code in the android source tree. Thanks for this feedback.