views:

55

answers:

2

I have a list view with 100 different images. My cache looks like the following,

public class ImageCache {
    HashMap<String, SoftReference<Drawable>> myCache;
    ....
    ....
    public void putImage(String key, Drawable d) {
        myCache.put(key, new SoftReference<Drawable>(d));
    }

    public Drawable getImage(String key) {
        Drawable d;
        SoftReference<Drawable> ref = myCache.get(key);

        if(ref != null) {
            //Get drawable from reference
            //Assign drawable to d
        } else {
            //Retrieve image from source and assign to d
            //Put it into the HashMap once again
        }
        return d;
    }
}

I have a custom adapter in which I set the ImageView's icon by retrieving the drawable from my cache.

public View getView(int position, View convertView, ViewGroup parent) {
    String key = myData.get(position);
    .....
    ImageView iv = (ImageView) findViewById(R.id.my_image);
    iv.setImageDrawable(myCache.getImage(key));
    .....
}

But when I run the program, most of the images from the ListView disappears after a while and some of them are not even there at the first place. I replaced the HashMap with a hard reference instead. Like,

HashMap<String, Drawable> myCache

And that piece of code works. I want to optimize my code. Any suggestions.

+1  A: 

There's a known issue with SoftReference in Android. They may be freed to early, you can't rely on them.
http://groups.google.com/group/android-developers/browse_thread/thread/ebabb0dadf38acc1
To solve that I had to write my own SoftReference implementation.

Fedor
+3  A: 

This code looks broken:

    if(ref != null) {
        //Get drawable from reference
        //Assign drawable to d
    } else {
        //Retrieve image from source and assign to d
        //Put it into the HashMap once again
    }

If the soft reference has been disposed, you will end up in the first condition, not detect it, and not reload the image. You need to do something more like this:

    Drawable d = ref != null ? ref.get() : null;
    if (d == null) {
        //Retrieve image from source and assign to d
        //Put it into the HashMap once again
    }
    //Get drawable from reference
    //Assign drawable to d

The platform use weak references extensively for caches of drawables loaded from resources and other things, so if you are getting things from resources you can just let it take care of this for you.

hackbod
I didn't realize that, thank u @hackbod
Ragunath Jawahar