2

On Android pre-honeycomb, Bitmaps have freaky memory issues because their data isn't stored in the VM. As a result it isn't tracked or removed by the GC. Instead it is removed when Bitmap.recycle() is called (and that is also done automatically in the Bitmap's finalizer).

This leads to some problems when doing image caching. When a bitmap is due to be evicted, I can't simply call recycle() on it, because I have no idea if anyone else is using it.

My first thought was to do System.gc() just before I load each bitmap. That way, hopefully orphaned Bitmaps will be finalized and the native memory freed. But it doesn't work. Edit: Actually it does sort of work. I had my System.gc() in the wrong place, after moving it, and halving my cache size (to what seems like a ridiculously small 2 MB of uncompressed bitmap data), my app no longer seems to crash (so far)!

My next thought was to implement manual reference counting, by subclassing Bitmap and calling ReferenceCountedBitmap.decrementCount() in all my activities' onDestroy() methods. But I can't because Bitmap is final.

I am now planning a BitmapManager which keeps WeakReference's to the bitmaps, and has methods like:

public void using(Bitmap bm);
public void free(Bitmap bm);

which count the references.

Does anyone have any experience or advice handling this? Before you suggest it, I can't ignore 80% of the market.

Community
  • 1
  • 1
Timmmm
  • 88,195
  • 71
  • 364
  • 509

1 Answers1

0

Well, I solved this with a bitmap manager, where I save the referencing views. In a map-like structure bitmap -> list of views.

Before I call recycle() on a bitmap, I first set all the references from the views to null (otherwise it will throw bitmap recycled exception).

Manual garbage collection, as you say, doesn't work for bitmaps pre-honeycomb, since they are allocated in the native heap and even with System.gc() you can't make assumptions when this memory will be released.

User
  • 31,811
  • 40
  • 131
  • 232