1

So I have an image slider which is a ViewPager with an image that you can swipe horizontal to move to the next one.

Before loading new images into the image slider I call mBitmap.recycle() on each bitmap to make sure I'm not wasting memory

Checking the memory monitor in Android studio reveals that in Android 4.4 (Dalvik) this works properly and every time new images are loaded, it always goes down to the amount of memory it uses when no images are loaded.

In Android 5.0 and up, that's not always the case. If you scroll sideways and view each image in the image slider at least once, when you go to load a new set of images, there's some leftover garbage that doesn't get collected, which is odd since I explicitly called recycle() on every image.

This crashes phones with lower heapSize (like 96MB), and on phones with larger heapsize (like 256 MB), you can compound this issue a couple times, up until about 100MB of uncollected garbage, and 90MB of legit used memory.

Once it hits that point of 190/256MB it seems like the garbage collection system starts "working" but I'm still not sure the Bitmap.recycle() calls that are actually doing the work. When the heap needs to readjust itself, it frees up a lot of memory each time, like 20MB, but simply invoking garbage collection (by clicking the button in Android studio) doesn't do that, it only removes the small amount of overhead when sliding between images.

So to summarize: Bitmap.recycle() is performing as expected if the images in the image slider / ViewPager are not seen, but if you see each of them at least once, the garbage collection somehow seems to be ignoring Bitmap.recycle()

Here's an image showing what exactly I'm talking about (this is for Android v5.0(ART), see the other image for v4.4(dalvik).

enter image description here

If you have any questions about my explanation of what's happening, I can clarify.

EDIT: Here's what it looks like when the same actions are performed on Android 4.4. Notice how every time recycle() is called it goes down to ~20MB of memory, which is about what my app uses not counting the bitmaps.

Image: Android v4.4 memory monitor example

user2322082
  • 658
  • 1
  • 6
  • 18
  • There isn't much you can do about the memory usage, and calling `Bitmap.recycle()` doesn't actually free the memory instantly as stated in the docks: https://developer.android.com/reference/android/graphics/Bitmap.html#recycle(), but you should consider decreasing the size and/or quality of your bitmaps depending on the memory available, as mentioned here https://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize. And if you aren't currently using a library to display bitmaps, have a look at one they tend to make the work much easier. – oiZo Jun 24 '16 at 19:02
  • Honestly the Bitmap.recycle() calls were added simply because Android v4.4 wasn't collecting the bitmaps fast enough for my app unless I explicitly added those calls. The calls may not be needed for v5.0+. Their non-instantaneous effect is obvious by the small climb in memory before the big dropoff as seen in this example image. Regardless of the necessity of including the recycle() calls, or their instantaneous/non-instantaneous effect, there are still bitmaps that are not being cleaned up and I'm unsure why. This is an issue because it crashes low memory phones on Android v5.0+. – user2322082 Jun 24 '16 at 19:24
  • My temporary workaround is to check if the phone is Android v5.0+ and if the phone has less than 200MB of memory, in which case force a low resolution for the image downloads. This prevents crashing, but does not allow the use of high resolution bitmaps like is possible in v4.4 with the same amount of memory. – user2322082 Jun 24 '16 at 19:26
  • Depending on what you are trying to show, you can also decrease the number of bytes used pr pixel with `Bitmap.Config.RGB_565` – oiZo Jun 24 '16 at 19:29
  • I'm using jpg images of the real world. Would that noticeably change the image quality? I'll probably experiment with it – user2322082 Jun 24 '16 at 19:33
  • It's very much dependent on the image content, but I use it my self for very low memory devices, as the other option is no image or an `OutOfMemoryException` neither of which seems like a better solution :-) – oiZo Jun 24 '16 at 19:36
  • I edited my post to include an image example of how it works properly in Android v4.4. Unfortunately I can't embed it. – user2322082 Jun 24 '16 at 20:09
  • Simply lowering the amount of memory the bitmaps used was enough of a workaround. Interesting that garbage collection starts working if you do that. I'm thinking that there probably needs to be something like 50 uncollected bitmaps before the garbage collection starts working right. There may be some sort of workaround in creating some low-memory garbage bitmaps that you don't even use. If I figure something out, I'll definitely post it. – user2322082 Jun 28 '16 at 19:29

0 Answers0