Monday, April 30, 2012

[android-developers] removing image data from memory

I have to believe there's a way to clear image data from memory once it's no longer required, but despite exhaustive searching I can't find a solution.  Both this list and stack are full of questions regarding OOM errors, specifically "bitmap size exceeds VM budget", but I still don't see a clear answer.

I understand there are hard memory limits on devices, and I understand it's not realistic to load up and display or cache large amounts of image data, but there should be away to discard data that's no longer required.

For example, imagine this very basic hypothetical app, that emulates a lot of the behavior of the native gallery app:

1. An image gallery that allows the user to peruse images from a remote server.
2. There might be any number of images on that server.
3. The app displays 1 image at a time, and allows a user to go back or forward 1 image at a time through button presses or swiping.
4. There'd be a maximum of 3 images rendered at any one time (so the user can see the one immediately to the left or right of the current image when swiping).  All other image data should be discarded.
5. Images are loaded using URL.openStream and Drawable.createFromStream or BitmapFactory.decodeStream.  Streams are closed appropriately.
6. Images are sized appropriately *on the server* before being fetched.
7. Loading happens in AsyncTasks.  Tasks that are no longer needed (due to moving away from an image with an incomplete task) are cancelled.  Any references in the AyncTask are WeaklyReferenced.
8. When any image is no longer required, it's "cleared" via:
  A) getBackground().setCallback(null)
  B) Listeners are set to null
  C) setImageDrawable/Bitmap(null)
  D) removeView

This simple construct, that takes into account all the suggest practices I'm aware of, will inevitably crash with an OOM error at some point.  Using BitmapFactory.Options inSampleSize and inPreferredConfig will delay the inevitable, but not forever, and at the cost of image quality.  In this example, I've used remote images, but the issue exists with images stored in /assets/ or in internal memory, etc.

My feeling is that if we can display X amount of image data at one point, and we take all steps to remove that image data from memory, we should be able to display that same amount of data later, without having to compensate for what has happened before.

With the sheer quantity of questions about this very issue, I'd hope to have a standard solution documented, but if there is one, I can't find it.  I've seen answers posted by Romain Guy, who otherwise seems very generous with his knowledge and active in the community, that say something like "Simple.  Don't use so much memory".  OK.  Tell me how.

Am I missing something fundamental?  Is there a way to discard image data once it's no longer being used?  What is missing from the above to create a simple photo gallery?  Assuming the built-in gallery app uses the FW, I imagine there has to be a way...

TYIA.


--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

No comments:

Post a Comment