I am working on an application that makes use of a dynamically populated list view of which each item contains an image that needs to be downloaded. Additionally, when clicking on any item in the list, it opens a detail page which once again shows the same image in addition to a few more.
As we know, it is best to use an async task to do the actual download and good practice to use a caching mechanism to both speed up image display as well as minimize actual data usage in multiple downloads.
After searching around for quite a bit, I ended up using the Google example code located at http://developer.android.com/resources/samples/XmlAdapters/src/com/example/android/xmladapters/ImageDownloader.html which claims to be both an async and caching method to download images.
The problem I am having, when called, this class does not appear to be caching the images correctly. So here goes ....
The portion of code in my custom class (that builds the list view) where I call the image download is this:
ImageDownloader getimage = new ImageDownloader();
getimage.download(logoURL, ivLogo);
With ImageDownloader being the class referenced above.
Images load, but it is apparent they are loading from the web each time. I added some logging into ImageDownloader.class to help track what is happening when. What I found, the first time the image is requested, it fails the first call to get from cache (as expected), getBitmapFromCache returns null and forceDownload is called.
public void download(String url, ImageView imageView, String cookie) {
resetPurgeTimer();
Bitmap bitmap = getBitmapFromCache(url);
Log.i(LOG_TAG, "Bitmap is: " + bitmap);
if (bitmap == null) {
Log.i(LOG_TAG, "Forcing Download");
forceDownload(url, imageView, cookie);
} else {
cancelPotentialDownload(url, imageView);
imageView.setImageBitmap(bitmap);
}
}
As execution progresses down the class to the point where it adds the image/url to the cache
private void addBitmapToCache(String url, Bitmap bitmap) {
Log.i(LOG_TAG, "Incoming Add Cache Info: URL: " + url + " Bitmap: " + bitmap);
if (bitmap != null) {
Log.i(LOG_TAG, "Entering the add image to cache section");
synchronized (sHardBitmapCache) {
sHardBitmapCache.put(url, bitmap);
Bitmap returnedbitmap = getBitmapFromCache(url);
Log.i(LOG_TAG, "Returned bitmap immediately after adding: " + bitmap);
}
}
}
I added logging to both verify the cache was added, and then performed a getBitmapFromCache, and the logs show the returned bitmap/url hash returns properly.
Incoming request to get Image, URL: http://www.yourlogoresources.com/wp-content/uploads/2011/11/Wendys-logo.png
Trying Hard Cache with URL: http://www.yourlogoresources.com/wp-content/uploads/2011/11/Wendys-logo.png
Hard Bitmap is: null
Trying Soft Cache with URL: http://www.yourlogoresources.com/wp-content/uploads/2011/11/Wendys-logo.png
Return from initial entry call: null
Entering forced Download
Incoming Add Cache Info: URL:http://www.yourlogoresources.com/wp-content/uploads/2011/11/Wendys-logo.pngBitmap: android.graphics.Bitmap@40762f28
Entering the add image to cache section
Trying Hard Cache withURL: http://www.yourlogoresources.com/wpcontent/uploads/2011/11/Wendys-logo.png
Hard Bitmap is: android.graphics.Bitmap@40762f28
Returned bitmap immediately after adding:android.graphics.Bitmap@40762f28
So it appears the cache is being populated properly, however, the next time that image is requested (ie when you scroll the listview), the cached image is not found again with getBitmapFromCache(url) returning null from the entry point download.
Incoming request to get Image, URL: http://www.yourlogoresources.com/wp-content/uploads/2011/11/Wendys-logo.png
Trying Hard Cache with URL: http://www.yourlogoresources.com/wp-content/uploads/2011/11/Wendys-logo.png
Hard Bitmap is: null
Trying Soft Cache with URL: http://www.yourlogoresources.com/wp-content/uploads/2011/11/Wendys-logo.png
Return from initial entry call: null
Entering forced Download
So I am at a loss here as to why it appears the cache is populated, but when it is checked again, nothing but null is returned.
EDIT
I ended up using a static reference to the ImageDownloader from my main Activity as follows:
public class myActivity extends Activity implements OnClickListener {
public final static ImageDownloader GetImage = new ImageDownloader();
Then called that like this anywhere I needed an ImageDownload:
myActivity.GetImage.download(logoURL, ivLogo);
Thanks for all the help folks.