23

Android's BitmapFactory.Options.inPurgeable has been recommended in various places as a way to avoid OutOfMemory exceptions in Android 2.x and earlier (Android 3.1 fixes this).

If inPurgeable is so great, why would I ever NOT want to use it? The documentation seems very light on details about what this option is doing:

If this is set to true, then the resulting bitmap will allocate its pixels such that they can be purged if the system needs to reclaim memory. In that instance, when the pixels need to be accessed again (e.g. the bitmap is drawn, getPixels() is called), they will be automatically re-decoded

Seems great. What's the catch?

Community
  • 1
  • 1
emmby
  • 99,783
  • 65
  • 191
  • 249

4 Answers4

9

The documentation has subsequently been updated with additional information which addresses your original question.

Summary: use of this flag is no longer recommended.

AdamK
  • 21,199
  • 5
  • 42
  • 58
4

If your are reading your bitmaps from the filesystem, using this flag wil force Android to keep the file open (at least in 4.0.4) to be able to re-read it. After reading more than 1024 files, you will reach the limit of opened files and get a "Too many open files" error.

You can observe the beahavior by using the lsof command from a rooted terminal and review all opened files.

pcans
  • 7,611
  • 3
  • 32
  • 27
  • What are you meaning by "from the filesystem"? Did you mean taken pictures by camera, or selected images from Gallery too? – Dr.jacky Nov 11 '16 at 12:37
2

This flag is currently completely ignored, that's the catch.


Update by @slodge: please anyone who is reading this and seeing it as the correct answer also read the comments - 'This flag is currently completely ignored' is true in certain cases only - in other cases (e.g. when using decodeByteArray on downloaded data) then this flag is not ignored and is very, very useful

Stuart
  • 66,722
  • 7
  • 114
  • 165
Romain Guy
  • 97,993
  • 18
  • 219
  • 200
  • lol, I just logged back in to edit my question to remove the part that said "it does seem to make my app better behaved when loading many images" when I saw your comment. – emmby Aug 15 '11 at 17:52
  • I've run the ApiDemo's "PurgeableBitmap" activity and it seems to consistently run out of memory at 128 or 122 (depending on device) with the NonPurgeable, but Purgeable is consistently 200 on both. This suggests the flag is not completely ignored. Can you expand on this at all? Thanks – Kevin TeslaCoil Aug 27 '11 at 04:52
  • Romain, by "currently", do you mean Honeycomb+? Because the "external' memory problem has been resolved? – Artem Russakovskii Sep 30 '11 at 20:46
  • By currently I mean "any available version of Android." And I don't know what external memory problem you are talking about. – Romain Guy Sep 30 '11 at 23:26
  • Romain, this setting most definitely fixes the OOM issues and the "external" memory (as reported by GC messages) ballooning out of control and running the VM out of memory. I tested on Gingerbread in both VM and real devices. There is no way it can be completely ignored as without it, I couldn't even scroll through a [sufficiently long] ListView with Bitmaps without crashing OOM. – Artem Russakovskii Oct 04 '11 at 18:40
  • 1
    Romain, I looked at the source and found that decodeByteArray() calls nativeDecodeByteArray(), which then definitely uses inPurgeable (not sure exactly for what, but it's used for copying memory). See http://google.com/codesearch#uX1GffpyOZk/core/jni/android/graphics/BitmapFactory.cpp&type=cs&q=nativeDecodeByteArray&exact_package=git://android.git.kernel.org/platform/frameworks/base.git&l=418 and http://google.com/codesearch#9OZVrqQu3Xg/trunk/googleclient/third_party/skia/files/src/core/SkStream.cpp&type=cs&q=SkStream.c. Am I too far off here? – Artem Russakovskii Oct 04 '11 at 21:25
  • 3
    Looks like it's used with decodeByteArray, which I didn't know you were using. It should definitely be ignored with decodeResource for instance. – Romain Guy Oct 04 '11 at 21:51
  • 6
    Heh, never said which function we were using, but your reply made it seem like it's not used by anything. – Artem Russakovskii Oct 04 '11 at 22:11
  • decodeByteArray crashes every time I don't use inPurgeable, even on ridiculously small images (4Ko…) – njzk2 Oct 11 '11 at 15:16
1

For the re-decode to happen, the bitmap must have access to the encoded data, either by sharing a reference to the input or by making a copy of it.

If you don't have access to the encoded data anymore, then this could be a problem right? What if you were live decoding bitmaps from a streaming ByteArray and your application just decides to reclaim the memory, wouldn't that cause your Bitmap to lose those pixels?

citizen conn
  • 15,300
  • 3
  • 58
  • 80