0

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.

asked Aug 29, 2012 at 14:10
6
  • Really difficult to determine without seeing code. Commented Aug 29, 2012 at 14:12
  • If your ImageViews retain alive, you should double check your recycling in your adapter. There should be roughly only the same amount of views like you see on screen. Commented Aug 29, 2012 at 14:22
  • I don't recycle them - should I ? I mean if I recycle them then it will throw an exception about frames that imageviews lack. Is there anyt workaround here? Commented Aug 29, 2012 at 14:26
  • An adapter should always recycle the views. Search for viewholder and convertview. Commented Aug 29, 2012 at 14:46
  • 1
    Assuming that you create Bitmaps dynamically when required and you use only unique bitmap instances for each row in a ListView you should be able to recycle() them if you find one in a convertView. 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 an ArrayList<Bitmap> or equivalent with images for every item in the list. Commented Aug 29, 2012 at 18:07

4 Answers 4

1

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)

answered Aug 29, 2012 at 14:28
Sign up to request clarification or add additional context in comments.

2 Comments

In depth my app can consist of 10 or even more activities. While navigating to 10th activity previous fragments' onDestroyView never gets called. Is there any workaround for recycling bitmaps manually and restoring them preventing frame exception ? I would appreciate an example
don't have examples :( "previous fragments' onDestroyView never gets called" that should not happen, once you navigate away from an activity - the "Called when the view hierarchy associated with the fragment is being removed." part should trigger. But Idk if there are ways to prevent that except for killing the app
1

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

answered Aug 29, 2012 at 14:14

2 Comments

do you know any example of open-source app that makes use of weak references and basically deals with memory management ?
I do not. Going only on what you have said, I would destroy all references in the onPause() and recreate them in the onResume() event for each activity. That way only the current activity references will be in memory. Also, if you are not doing so and your app gets paused - for an incoming call etc - and your app gets killed by the OS you have just LEAKED all that memory.
1

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.

answered Aug 29, 2012 at 14:17

3 Comments

so you want to say it's still a manual approach and Android won't use say LRU algorithm to destroy views/free bitmaps ?
Android should do a pretty good job of this natively, but it is difficult to diagnose your problems without seeing code. If you are preventing old activities from being destroyed (stopping onDestroy(), for example), then you are interfering with the built in memory freeing process. But yes, Android does place a good deal of responsibility for memory management on the developer.
While it probably sounds old-school, good memory management is still borne upon the programmer. You know your app best. You have to ask yourself what is really needed at any given point and time and get rid of anything else - don't rely on the OS to do it for you.
0

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.

answered Aug 29, 2012 at 14:29

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.