Android: layouts with deallocated components after resuming activity (memory issue?) - android

My application has several components including a ListActivity and a MapActivity. I'm running into a weird problem where parts of those activities seem to be deallocated after resuming my application from background.
It's fairly deterministic. I'll return home from my application, then run other application/go on browser and then return to my application. Then my MapView disappears and other components are gone or distorted. Anyone run into something like this?

Memory is taken back by the system if it goes onPause() and the memory is needed by other Apps (Garbage collection). You need to put setContentView of your activities in your onResume() method overload if you need it to resume the old status. Check the activity life cycle

Related

Should I let go of view-references etc in onStop() or onDestroy()?

Should I let go of views and other data i'm holding on to in onStop() or onDestroy()?
If I release my application's data in onDestroy() it won't be very memory-friendly towards android, am I correct? Since i'm still holding on to a couple of views after onStop(). Plus it's not guaranteed to be called and my Activity is purged from memory anyway.
If I release it in onStop(), I have to add do my setContentView() etc. in onStart() which doesn't get the Bundle that onCreate(Bundle) is handed.
Note that I have a very large application which consists of dozens of Views, most of which are custom and added by code rather than layout-files. This is largely due to the fact that I had to create a custom pager to flip through pages, since none of the built-in Views could serve my purposes (I've tried… hard…).
I have read through all the relevant Android docs but I still have no real clue on what about the view-hierarchy Android saves/recreates by itself and what I have to do myself. Or when all of that happens, meaning when Android removes the view-hierarchy from memory.
Update Question:
The android docs says this: Note: Because the system retains your Activity instance in system memory when it is stopped, it's possible that you don't need to implement the onStop() and onRestart() (or even onStart() methods at all.
If it's ok to hold on to everything, why should I care about memory-leaks when my application is being stopped like this article says? If it's destroyed and re-created, for example after a screen-rotation, I'm starting from scratch anyway?
No, you do not have to let go of anything in onStop() or onDestroy() if you only hold it in your activity (in its non-static fields). When Android let's go of your activity, the rest of your stuff is automatically thrown away (along with the activity), because there is no way to reach it from any thread (this is how Garbage Collectors work, it is not in any way special or specific to activities).
The article you refer to describes the problem where a reference to a view (or a drawable, or - broadly speaking - activity context) survives the activity that created it. Since there is a reference pointing back to the already dead activity, it becomes a zombie; what's more, it clings to all its fields, effectively zombifying them too. So if you have a view or a drawable and put it in a static field (or in any other place that might survive your activity object), then yes, you have to let it go in onStop() or onDestroy() of the relevant activity.
If Android destroys your Activity and forgoes calling onDestroy(), it means that the whole process was taken down, and this means that no memory leak can occur anyway (they are local to a single process)
Bonus answers:
views inflated from XML files take exactly as much memory as ones built in code. Why should they be heavier?
(update, after a comment) before an activity gets thrown away, Android walks its whole view hierarchy and gives each view a chance to store its state (any parcelable data) into a bundle; when recreating view Android walks the tree again and gives the data back. This is why when you recreate an activity the state of the view is saved (focus, position, content of text fields etc.). Observe how the state is only saved for elements that have an id (does not matter if they are inflated or created dynamically).

Android - Losing scope on UI elements after onDestroy()

I am trying to handle problems that occur in my application when the phone is plugged into certain types of chargers and put into "Car Mode" or "Driving Mode".
In the running application, onDestroy() is called and immediately followed by onCreate(), and the application starts again normally. However, subsequent calls to update UI elements (in the newly created main Activity) now have no effect, and it looks like I've lost scope on my layout.
RelativeLayout splash = (RelativeLayout) findViewById(R.id.splash);
splash.setVisibility(View.VISIBLE);
What could be ocurring onDestroy() that I'm not accounting for? I don't do much cleanup onDestroy because I didn't think I needed to.
The Activity has been detached from the UI by the time onDestroy() is called so having UI calls to it doesn't make any sense. If you need the splash to be shown, set it to View.VISIBLE in onCreate(), onResume(), or maybe onPause(). I'm not entirely sure if onPause() would act any different.
When the phone rotates the activity is destroyed and recreated. Plugging into a car charger usually forces the phone to landscape mode, thus rotating it (from portrait, most likely) and calling onDestroy. There is a way to prevent this behavior with some activity flags -- but Google advises against it.
We need to see some more code for this Activity to figure out what's going on.
Also, as DeeV points out, the activity is long gone by the time onDestroy gets called, so it might not be the right place to be doing whatever it is that you're doing -- but we need more code to be sure.
As a sidenote, sliding the keyboard up (on phone's that have slideout keyboards) will produce the same effect.

Is it safe to deallocate resources in onStop()?

Hi All!
I have an Activity which allocates quite lot of memory while it shows a visible layout. The UI heavily depends on this memory, however, there is no need to keep these allocations after the user traverses away from the Activity (usually by bringing another Activity to focus).
The Activity starts to allocate memory in onResume() and all is fine with that. It's the deallocation that confuses me a bit, though. As of now I release all memory in onPause() which also destroys the corresponding UI elements. Since the Activity is still visible while running onPause() the user will see the actual UI elements becoming destroyed. This is ugly and not what I want.
So my question:
Is it safe to release memory (destroy UI) in onStop() (according to documentation the Activity is not visible when onStop() is called)?
Is onStop() reliable?
Is onStop() guaranteed to be called every time when onPause() is called?
Edit:
I feel I must explain a bit more clearly what confuses me. According to developer.android.com:
...for those methods that are marked as being killable, after that
method returns the process hosting the activity may [be] killed by the
system at any time without another line of its code being executed...
The onStop() method is marked as "killable".
Does the above mean (especially the "after that method returns" part) that the entire scope of onStop() is guaranteed to run, but once it returns nothing else is guaranteed any runtime (e.g. a spawned thread started in onStop())?
Or does it mean that onStop() might get interrupted even before it reaches the end of its scope (as of the killed at any time part)?
Or does it mean something else that I - in my divine stupidity - don't see.
The difference is that the activity sees to it that onPause should finish executing first before "destroying" the view, while onStop is a lifecycle stage that follows after the view is already in the background - meaning the activity is not visible anymore.
doing things inside onPause makes sure that the items you need to save are still intact before letting go of them - for example you need to save the text in your EditText, or the on/off position of RadioButtons, etc.
deallocation however doesn't need any of these things anymore, so it should be fine if you do it in your onStop
onStop() should be safe and reliable enogh for your purpose.
"Guaranteed" is relative in this case, given that your activity may be killed without any notification. But in that case your memory resources are released anyway.
it's as safe as anything else? Worse comes to worse your app will be killed with onDestroy. In mobile development, you basically have to assume that at any given moment your app could be killed.
It's been reliable for me in releasing media objects for a while now.
Not really guaranteed, as sometimes onDestroy is called depending on what's going on.
No, it is not safe as only onPause() is guaranted to be called. onPause() means that yor activity loses focus - perfect place to give away not necessary resources

Android - memory leaks, what am I doing wrong?

I have activity A, which launches activity B via an intent. Activity A has no references to Activity B, there are also no references to Activity B in the Application singleton I am using.
When I create Activity B, several thousand objects are created. That's okay, it's an activity with a very populated ListView with lots of images.
But, when I press the back button and return to Activity A, only about a dozen of the several thousand objects are released. onDestroy() is also called for the activity. I'm using DDMS to view the heap info, and am pressing 'Cause GC' several times to force it to free memory.
I've done the same test on other apps (that use list views too) and 100% of their objects are destroyed on pressing the back button then 'Cause GC', so it's certainly not a bug.
Any advice please? :-) I've read the material in the android docs about leaking contexts, but that's not helpful since i'm not referencing the activity (or anything in it) being destroyed elsewhere. Also, I have many other activities which work the same way, and don't release all memory on destroy. I must be missing something obvious?
Edit: I just realized i'm using AsyncTasks which have references to the activity (either passed as arg into doInBackground() or accessible via outerClass.this. Could they be hanging around in the thread pool, even after onPostExecute() ?
Edit: It leaks even if I go back before running any asynctasks :-(
Edit: No leak before running asynctasks if I remove admob code, but still leaks in the activites which do use asynctasks.. so asynctask is still a good candidate :-)
I believe there's a bug in the ListView implementation. Take a look at this question: Android: AlertDialog causes a memory leak.
Here's a bug report: http://code.google.com/p/android/issues/detail?id=12334. It's declined but in my opinion it must be reopened.

android memory management in activity lifecycle

My question is a little bit complicated.
I want to understand how the app treats resources (especially images for backgrounds, buttons, etc.) when Activity is started, then suspended.
For example, I start Activity A, it shows all the images on the screen, eats its memory, then another Activity B is started and A is suspended. What happens to all the images, resources, etc.? When they are freed? How can I take control over them? Should I not keep the Activity A in the memory and remove it from the Activity stack?
If you need any clarification for my questions, pls write me!
Thanks in advance!
Danail
Activity doesn't free resources until it's finished. But in most cases it mustn't be a problem for you. In my opinion, you shouldn't add your own resource management and make your code complicated in most cases.
But if you really think that your app can be out of memory, you should check it with something like MAT. Problems with memory may be caused by memory leaks, not heavy memory usage.
Eventually, when you're absolutely sure that you have to do something to reduce memory usage, you can do some memory optimization. For example, you can save memory-consuming objects (e.g. large images) to local storage in onStop() and load them in onStart(). I think using onPause()/onResume() for this purpose is a bad idea, because Activity is partially or even fully visible.
In theory, you can even destroy all your widgets in onStop() and restore them in onStart(), but it can make your app too slow. And, of course, in this case state saving must be implemented by you.
Finishing activities may seem to be a good idea, but I think it's not. Firstly it makes your work slower. Secondly you must manage activity stack and state of activities yourself.
For example, Activity A starts Activity B. So, Activity B must know what to do when user presses Back button. When user presses back button you should start Activity A and restore its state. But what if user terminates this app. In this case you must initialize Activity A with its default state. So, you have to implement a lot of additional logic.
In conclusion I'll repeat the main idea one more time: don't optimize memory usage if you aren't absolutely sure you have to!
Okay so we have the following situation:
A > onCreate
A > onStart
A > onResume
A > Use up a load of memory (A could even use up too much and crash)
A > Launch activity B
B > onCreate
A > onPause
B > onStart
A > onStop
B > onResume
B > Use up a load of memory
If B uses up enough memory then the Android system will kill activity A (you'll notice the onPause and onStop methods of A have already been called so it's already been given a chance to save it's state)
If you then press the back button the Android system will just start activity A again (and if it's clever it should remember it's last state) so it looks like nothing ever happened to the user.
So to be a bit clearer: if you start B and then finish A, B will essentially just replace A in the activity stack and pressing the Back button in activity B will just exit your and app and not return to activity A.
If on the other hand you start B without finishing A, then pressing the back button in B will take you back to A. While activity A is in the background it could be killed to reclaim memory, but Android will recreate it as needed when the user navigates through the activities stack.
Also if you have in memory-caches of multiple objects (e.g. bitmaps/drawables) then back your collection by SoftReferences so that the GC can clear them up if it's running low on memory.
You should design your app so that it's memory usage is low, but you can count on the framework do it's best in memory management. So, do not work too hard with removing unused stuff, only in cases when it's obvious that your app is eating too much memory.
When the available memory goes down, the framework will stop and remove activities and services which are not associated with the current task. If your app eats up even more memory, the framework will stop your activities which are in the background. Then comes the services associated with your app and the last one to finish off will be the current activity.
When the framework stops an activity it does keep record of the activity stack, the intents used for starting the activity and the bundle returned by onSaveInstanceState(), so it can recreate the last known state of the activities. Also, the framework can unload unused resources (drawables, etc.) when not in use and reload them when needed.
Well before replying to your questions, I have certain facts to discuss.
As per the life cycle of the Activity, if we call finish() then the onStop() called and finally the onDestroy() which eligibles that Activity for Garbage Collection and remove from the Activity Stack of Android.
Android is maintaining the Drawable cache for the Activity designing and displaying on the screen. So if you disable the drawable cache on the Activity onCreate().
So the best practice is to disable drawable cache on the onCreate like this:
LinearLayout v = (LinearLayout) findViewById(R.id.mainLayout);
v.setDrawingCacheEnabled(false);
and to call finish(); on the onPause();
You have very little control over memory when you writing Java code. This is a good thing for most of the cases. Actually most of the application do not need to worry about memory.
To answer your question, all the object for activity A will still be in memory when it is suspended. VM will start GC when it needs resource.

Categories

Resources