0

I'm working with some Classes that holds a reference to a Bitmap like the following:

class Picture {
    private String localPath;
    private Bitmap bitmap;
    // setters and getters....
}

Then on certain fragments I use picture.setBitmap(BitmapUtils.decodeBitmap(picture.getLocalPath, size)); to get a reference and afterwards set it to an ImageView. But I'm never doing bitmap.recycle() or bitmap = null; explicitly.

I'm not really sure how does bitmaps works internally and why the GC wouldn't collect them in some situations, so I want to know if what am I doing might cause a memory leak, and how can I prevent this, given the fact that bitmaps reference are only stored on an object as a holder

Edit: since it seems to be some kind of confusion on what am I doing with the Bitmap, I'll explain some more. The business model in the information system defines a couple of entities that have images as attributes (for example, a profile, which the user have a profile name, and a profile picture).

It is indeed true that in cases like that, you normally would keep the picture path as the attribute instead of the picture itself. But since I'm taking several pictures from the Android camera, I'm saving it to a list to perform batch operations. You can see it as if the entity works as a holder for the picture itself, since you need a reference to each picture to perform batch operations on them.

Christopher Francisco
  • 15,672
  • 28
  • 94
  • 206

2 Answers2

1

edited answer: I read your edited question and I still believe you shouldn't be holding the bitmaps, and I'll explain why.

I'm taking several pictures from the Android camera, I'm saving it to a list to perform batch operations.

That "list", how big is it going to grow? 1 or 2 images? several images? it's unlimited, only depends on the user usage?

So let's imagine a very common image size nowadays, even mid-range phones have, 5 MP. That's 2560x1920 pixels, which rounds to precisely 4.915.200 pixels. If you're using best quality Bitmaps (Config.ARGB_8888), each pixel will take 4 bytes of memory. That will result in:

4.915.200 x 4 / 1024 / 1024 (in megabytes)

So each image will take 18.75 megabytes of RAM space per Bitmap.

I haven't check Android VM heap size lately, but the first ICS devices were around 48mb heap size. That means your code plus a couple of images and your app will throw OutOfMemoryError.

To conclude:

I still think you should save only a String reference to the JPG generated by the camera (if you're not generating the JPG and only acquiring the Bitmap, go ahead and save this Bitmap in disk using this code) then queue on your array the String, once your code reach the String then you decode your bitmap, do your processing and then immediately get hid of it.

original answer:

I might be wrong, but I believe that you're trying to re-invent the wheel, and you shouldn't.

It seems to me that you're trying to do some type of bitmap caching/decode which is a fairly complex and delicate subject as it involves threading and mobile memory restrictions.

Said all that my suggestion is to simply use a library that already handles all that for you. My personal favorite is Picasso http://square.github.io/picasso/

with it, all you have to do is:

Picasso.with(context).load(path).into(imgView);

that's all. The path can be pretty much anything you would need, such as SD-card, URL.

Community
  • 1
  • 1
Budius
  • 39,391
  • 16
  • 102
  • 144
0

According to Android developer website:

On Android 2.3.3 (API level 10) and lower, using recycle() is recommended. If you're displaying large amounts of bitmap data in your app, you're likely to run into OutOfMemoryError errors. The recycle() method allows an app to reclaim memory as soon as possible.

Caution: You should use recycle() only when you are sure that the bitmap is no longer being used. If you call recycle() and later attempt to draw the bitmap, you will get the error: "Canvas: trying to use a recycled bitmap".

My recommendation is check how many images you are displaying and size of each of them. If you are displaying large number of images then use lazyloading libraries like Universal image loader. I rarely use bitmap.recycle because after you recycle a bitmap you can never use it again.

Pang
  • 9,564
  • 146
  • 81
  • 122
Illegal Argument
  • 10,090
  • 2
  • 44
  • 61