1

I'm working in a project that opens an image, plays with it, and saves. The image can be a very huge image, like a camera pic, so I'm doing several things to ensure not getting OutOfMemory exceptions (basically what appears here http://developer.android.com/training/displaying-bitmaps/load-bitmap.html):

  • Perform all measurements of width and height of the image without actually open it, using:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(image_path, options);
  • Open images already resized ( inSampleSize ) and using Bitmap.Config.RGB_565 (2B per pixel) besides Bitmap.Config.ARGB_8888 (4B per pixel).

  • Using temp files to not having a lot of bitmaps in memory (actually I only have one most of the cases, max 2 when applying masks or so).

  • Recycling every bitmap after its use

  • When showing the result in a ImageView, open it already scaled to the screen sizes.

But, in some cases, when it's impossible to have only one bitmap loaded at a time to do a certain work (rotating the image, fine tune resizing, apply masks, ...), and mostly in medium range or old devices, I get an OutOfMemory Exception.

I've started to add all the Image working in Background Jobs with something like the following (ok, I'm a newbie):

ProgressDialog dialog = ProgressDialog.show(this, null, "Please wait", true, false);
new Thread(new BackgroundJob(this, new Runnable() {
    public void run() {
        ImageHelper.ImageManipulation(image_path); 
    }
}, dialog, new Handler())).start();

I was hoping to get a completely memory free space with this new thread to perform there the Image manipulation tasks, but what I find is that the app crashes at same points for same reasons. Threads are created as a child process (ok) but sharing the max heap and the current used mem ...

Is there a way to open a thread to perform image manipulation having more memory to work (freeing the memory used by the activity itself as it is another thread, for example)?

Thank you very much.

Xavi
  • 162
  • 10

2 Answers2

3

There is lots of gotcha's when it comes to memory management on Android devices - especially when you throw in different devices into the mix. I've wasted last year playing with memory management in different Android apps I've made and it was not until I found Android-BitmapCache project that I made some significant progress.

I advise everyone who are interested in Android Memory management to download and inspect Android-BitmapCache project, because it contains some great code - so do that as a first step.

I would advise that your second step would be watching Google I/O: Memory Management for Android Apps mostly so you can start testing exactly how much your application is using memory, and tracking where EXACTLY memory usage starts increasing. Speaking of that - I don't understand why you think that you'll get "completely memory free space with new thread" - all threads that you spawn from your Android app will be under same process, so it doesn't matter which exact thread is running some task when it comes to memory usage.

And finally, you can fix problem temporary by using android:largeHeap="true", but I think you should definitely aim toward more robust solution. Keep in mind that it's possible that on some devices you app will simply not work (24MB heap and you want to load image that's 3000x3000), but with applying all best practices you can find in project I've linked I'm sure you'll be much better off.

nikib3ro
  • 20,366
  • 24
  • 120
  • 181
  • 1
    Thank you for your explanation! I'll check the project and that talk ... I'm definetivelly interested on manage this kind of memory issues when working with images. About the _largeHeap_ , i have it placed but don't see any difference. About the "completely memory free" thing is about a misunderstanding in my side: I thought I could open another thread and not inheriting the current consumption from the process... but since it is a child... – Xavi Mar 10 '13 at 12:35
  • @Xavi Glad I could help and feel free to ask more question - just if answer helped you mark it then. As for largeHeap - that attribute was introduced in Android 3.0 so it may not work if you have older device - for them you need to [play with VMRuntime](http://stackoverflow.com/a/15010854/237858). – nikib3ro Mar 12 '13 at 03:54
1

You could use pool thread to execute multiple threads, it's less "expensive" way comparing to create new Thread object for every thread.

This guide might help: http://developer.android.com/training/multiple-threads/create-threadpool.html

Or this http://android-developers.blogspot.com/2009/05/painless-threading.html

Rodion Altshuler
  • 1,713
  • 1
  • 15
  • 31