I am using the Android BitmapFun sample code to manage bitmaps in my application. I have been experiencing garbled or duplicated images in a ViewPager. I have tracked this down to the following code in ImageCache.java:
/**
* Notify the removed entry that is no longer being cached
*/
@Override
protected void entryRemoved(boolean evicted, String key,
BitmapDrawable oldValue, BitmapDrawable newValue) {
if (RecyclingBitmapDrawable.class.isInstance(oldValue)) {
// The removed entry is a recycling drawable, so notify it
// that it has been removed from the memory cache
((RecyclingBitmapDrawable) oldValue).setIsCached(false);
} else {
// The removed entry is a standard BitmapDrawable
if (Utils.hasHoneycomb()) {
// We're running on Honeycomb or later, so add the bitmap
// to a SoftRefrence set for possible use with inBitmap later
mReusableBitmaps.add(new SoftReference<Bitmap>(oldValue.getBitmap()));
}
}
}
The bitmap is added to the reusable bitmap list when it is removed from the cache. In this case the bitmap is still in use by a ViewPager view. When a later view is created the bitmap (still in use) is reused and the bitmap appears in two positions in the ViewPager.
A bitmap that is removed from the LruCache isn't necessarily available for reuse. I have disabled the reuse of bitmaps in this code and am no longer having an issue. This problem doesn't occur with lower resolution images because the bitmaps aren't removed from the cache while in the range of the ViewPager's offscreen limit. I don't have an issue with 60 DPI images but see this issue frequently at 160 DPI. I think this would show up in the original BitmapFun sample with higher resolution images.
Anyone else experienced this problem or I am not understanding the issue properly?
Kevin
What I think the problem with the code is in the line
That line adds a bitmap that was removed from LRU cache to a reusable bitmap set to be used for inBitmap re-use. It doesn't check whether it is still being used by an ImageView or not. If you try to re-use a bitmap that is still being used by an ImageView, the underlying bitmap will be replaced with another bitmap making it not valid anymore. My suggestion is to track whether a bitmap is still being used by an ImageView before adding it to the reusable bitmap set. I've created a sample github project for this issue. Tell me what you think with my solution.