Activites in my app contain fragments, which in turn contain listview/gridviews that're full of bitmap data. Eventually a user would run out of memory because views of the previous activities and their fragments don't get destroyed. So, when user has reached, say, 10th activity - 9 previous hold a plenty of bitmap data.
I'm already using weakrefences, however MAT says that some fragment's view holds reference to, for instance, Gallery which in turn holds adapter etc. So ImageViews retain alive and so do bitmaps.
So far I've experemented with completely removing fragments, removing adapters. Sometimes it works, but I wonder why should this be so complicated and if there's any simpler way to free/acquire without much coding ?
UPD
I would appreciate an example of open-source app where the same problems are challenged.
UPD2
Blueprint for most of my activities is: activity holds fragment. fragment holds AbslistView that are full of imageviews.
Thanks.
4 Answers 4
It is difficult to get it done without using up all the memory.
That requires on demand (re)loading, freeing memory on view destruction and careful design of your fragments and classes.
https://developer.android.com/training/displaying-bitmaps/index.html has some valuable information about loading images that way.
If you load all your images through some sort of asynchronous caching loader, clear the cache on onViewDestroyed or onDetached depending on your needs and don't keep other references to those bitmaps you should have removed most of your problems.
The lifecycle is pretty symmetrical (onCreate<>onDestroy, ...) so it's a good idea to null any references that you created in exactly the other side of that lifecycle part. Assuming you use appropriate places in the lifecycle you get a lot of memory management for free. In your case you should check that in case your fragments are retained you don't keep references to the Gallery or ImageViews (should only exists between onCreateView -> onDestroyView)
2 Comments
I would recommend keeping only that what you need in memory and destroy everything else. It is bad form to use up all available memory. I would look at the activity life cycle and understand it completely to resolve your issue: https://developer.android.com/reference/android/app/Activity.html
2 Comments
I recommend watching the Memory management for Android apps Google IO 2011 presentation.
You should also examine your app's workflow to determine when you can start destroying old activities or freeing other resources.
You can also use ActivityManager.getProcessMemoryInfo() to retrieve memory usage information for your process to aid in determining whether you need to free some old resources.
3 Comments
If your outofmemoryexception happens in your adapter's getView method,
You could isolate the line it usually happens and surround it with a try-catch like this :
try {
// load image (or whatever your loadimage is)
mViewHolder.thumbImage.loadImage();
} catch (OutOfMemoryError e) {
// clear your image cache here if you have one
// call gc
System.gc();
// load image retry
mViewHolder.thumbImage.loadImage();
}
Its not the most elegant solution in the world but it should help.
viewholderandconvertview.Bitmaps dynamically when required and you use only unique bitmap instances for each row in aListViewyou should be able torecycle()them if you find one in aconvertView. But auto recycling via GC worked fine for me in that case since there are only few small bitmaps required at a time when showing a list. Just don't have anArrayList<Bitmap>or equivalent with images for every item in the list.