Right so here I am obsessing over memory leaks, and quite frankly not understanding what could really lead to one (and yes I've read the usual links such as http://kohlerm.blogspot.co.uk/2009/02/memory-leaks-are-easy-to-find.html).
I've tried to create some on purpose, for example by leaving a PhoneStateListener subclass inside my activity and opened and closed it a bazillion time, can't see anything in DDMS heap or MAT out of the ordinary. Yet on SO I read over and over again that not only it needs to be deregistered onDestroy, but also onPause (PhoneStateListener() isn´t finished)
Question: is there such a list?
Bonus question: is it true that a PhoneStateListener will create leaks unless it's deregistered onPause/onDestroy etc.
UPDATE: I stand corrected. When re-spawning my app over and over again, even in singleinstance mode, the PhoneStateListener(s) it has registered are still alive after onDestroy was called, and start adding up. I'm currently working on an elegant way to kill them, and will post my results here.
UPDATE2: The correct way to deregister the listener is:
instanceOfTelephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
... according to the API
UPDATE3: As promised linking this to a better phrased question: https://stackoverflow.com/a/4607435/821423
It is good practice for activity to clean up after yourself and prepare to die in onPause() - this is always called before it goes out of focus, and can not interact with user. onDestroy() is possibly called after this (but not guaranted).
Is your activity is not in focus for user, it does not need any listeners anymore, as it can not show results of those listeners.
Related
I know this question has been asked a million times, I myself though that I already knew the answer and that the correct one was that the only guaranteed call is to onPause(), so you should save your data there.
However, in many places of android documentation they always suggest not doing heavy work (such as writing data in database) in the onPause() method as it will delay the transition between the activities.
According to Android Developer Guide in Table 1
onPause(): This method is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, and so on. It should do whatever it does very quickly, because the next activity will not be resumed until it returns.
Killable: YES
Then according to Android Developer Reference Guide in the similar table.
It says the same thing but:
Killable: Pre-HONEYCOMB
And they add a little note that says:
Be aware that these semantics will change slightly between applications targeting platforms starting with HONEYCOMB vs. those targeting prior platforms. Starting with Honeycomb, an application is not in the killable state until its onStop() has returned. This impacts when onSaveInstanceState(Bundle) may be called (it may be safely called after onPause() and allows and application to safely wait until onStop() to save persistent state.
Killable
Note the "Killable" column in the above table -- for those methods that are marked as being killable, after that method returns the process hosting the activity may killed by the system at any time without another line of its code being executed.
FOR POST-HONEYCOMB (i dont care about earlier versions):
So, is it OK to assume that any Android device (including different ROMS) will ensure a call to onStop on the activity? And this is the best place to make any time consuming storage writing of the App?
Note: This is extremely confusing as most answers here, sites, books, and even online android tests take as a correct answer that you should save it in onPause and NOT in onStop.
When to save data to database, onPause() or onStop()?
Either. They are nearly identical, particularly on Android 3.0+.
If the activity that is taking over the foreground is a typical full-screen activity, so that the earlier activity is no longer visible, onPause() and onStop() will be called in rapid succession.
If the activity that is taking over the foreground is themed to be more like a dialog, where the earlier activity is still visible, onPause() will be called, but not onStop(), until such time as the activity is no longer visible (e.g., user now presses HOME).
Most apps aren't worried about the "themed to be more like a dialog" scenario, in which case onPause() and onStop() are called one right after the next, and you can fork your background thread to save your data in whichever of those makes sense to you.
However, in many places of android documentation they always suggest not doing heavy work (such as writing data in database) in the onPause() method as it will delay the transition between the activities.
The same is true of onStop(), as both of those methods are called on the main application thread.
So, is it OK to assume that any Android device (including different ROMS) will ensure a call to onStop on the activity?
Both onPause() and onStop() will have the same characteristics from the standpoint of process termination. Either both should be called (normal case) or neither will be called (e.g., you crash, the battery pops out the back of the phone).
And this is the best place to make any time consuming storage writing of the App?
Either onPause() or onStop() are fine places to trigger the work, done on a background thread, to persist your data. If you prefer to do that work in onStop(), you are absolutely welcome to do so. Personally, I'm an onPause() kind of guy.
If you want more safety, storage in onPause.
If your data is so big that you have to storage it for several seconds, you may open a background Service (e.g. IntentService) to save.
You can also check the system version in your code and choose when to save. if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.ICE_CREAM_SANDWICH){}
In most situations this rule of when to save will not be changed by some customed os. But of course there can be some other os which certainly changed it. So the most important thing in android development is that u need to know that everything can be different in different phones.
I know this question is prehistoric, but it seems like people like me still happen to land on this question. So I guess it may make sense to add an answer I found in the documentation, which states:
To save persistent data, such as user preferences or data for a database, you should take appropriate opportunities when your activity is in the foreground. If no such opportunity arises, you should save such data during the onStop() method.
source
But wait, there's more:
Note the "Killable" column in the above table -- 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. Because of this, you should use the onPause() method to write any persistent data (such as user edits) to storage.
source
So wrapping up, it seems like persisting data onPause() is the best thing to do.
I'm trying to execute some code whenever my activity is killed, but not when it's simply moved to the background (so just calling it in onPause() isn't a solution), and I understand onDestory() is not guaranteed to be called. I've been searching all over and haven't found a way to do this. How can I go about tackling this problem? Is it possible?
Nothing. You can never be guarantied to be called when an app ends, because it can always be terminated abnormally- it could crash, the battery could be pulled out, etc. onDestroy is the closest you can come. But you should never write a program that requires cleanup at termination time.
I'm not sure, but I suspect you've got a few issues which you've conflated into one large issue;
As I read this question you have 2 or 3 concerns:
1) You want to garuntee something happens when the app exits.
2) You have state you want to maintain during onPause() but not after onDestroy()
3) You presumably have some content which should not persist between application usages.
Some answers:
1) As Gabe points out - there is no guarantee anything will ever be called. I can pop the back off the device and pull out the battery. Your calls aren't going to happen.
2) You might try onDestroyView() for this case. It won't be called in many circumstances in which onPause will be (for example when an alert dialog is shown), but will be called in others (when you replace a fragment with another fragment for example).
3) This issue makes me think you may want to reconsider your method of storing/saving this information. If you don't want it to exist on the system when you app isn't in use, it is best to never write the data to the filesystem. (Due to 1). Other options are keeping it in memory. You could also use shared preferences/preferences mechanism but this will still exist on the filesystem until your app is removed.
As you all knows all android activities create, start, resume, run, pause, stop, destroy. This process is shown well in the android manual.
In this lifecycle is there any possiblity to understand activity is created which way? I mean how can I understand whether activity is called directly or activity is created once then killed by android os and then recreated since user navigates back?
More basically how can I understand whether an activity is in its second life or first life?
Edit: Why do I need this?
In my design I have a main page where the data is loaded from the net. And when the user clicks some details, it puts the data in a static object just like session in web. This works well normally.
But when a user starts detail activity in second life, he data in static object is killed, and I got nullpointer exception.
I have 4 projects having same architecture so I want to solve this problem.
You've already got the flow chart information there. You can always keep some state for later use by storing the fact of your Activity's demise during onDestory() or similar. Then, the next time your Activity is resumed, you will know if you were actually destroyed or just stopped. I don't think you get any of that information for free from the OS, since it's not supposed to matter in the ideal case.
you should not distinguish between these, since even after it has been destroyed (at least the method has been called) it might "come back" just in the state as it was when it was destroyed. Which could be different than from the very initial state when it was created the first time.
Please explain the reason why you need this - you should "rethink" your issue, since Android is really behaving "strange" concering this question.
It is better to design your project livecycle according to Android system behaviour - which is actually not documented anywhere regarding this point (at least I have not come accross any good doc so far)
If I understand your question, you want to know when your activity has been destroyed by the OS or when it has only been paused. Simply use logcat statements:
onPause() {
super.onPause();
Log.v("Activity", "Paused");
}
onDestory() {
super.onDestroy();
Log.v("Activity", "Destroyed");
}
You can do the same for onCreate(), onResume(), anything really.
I dont think putting finish() in onPause() is cutting it.
I have a Location activity and it is proving very hard to test, what I would like to do is be able to, when I leave the activity, completely destroy/kill any existence of it. So that when I go back, both when I leave the app or just the activity, everything is new, there is no cache, nothing and it has to start all over again.
The reason being is I don’t want it to remember Last Know Locations, they are not useful in this app, all I want is the current location and if it can’t be found, it can’t be found.
Cheers,
Mike.
This gets into some deep discussions about how android manages activities and memory and all kinds of things which you probably don't want to think about.
If you are currently trying to finish the activity in your onPause method (sounds like a horrible idea to me since your phone will call this whenver your screen goes to sleep -- after about 15 seconds of inactivity depending on your settings). But if that really is what you want to do then why not just make the call to get the last known location in your onResume method?
Put finish in onPause and in manifest add this for that activity android:stateNotNeeded="true"
so it want remember your last state on relaunch of that activity
For solving this problem you can use preferences for storing the data and you can use it for future.
Can anyone give a short overview of the cases when and how an activity is killed by the runtime? I'd like to know the difference between the paused and stopped state. What could force the system to destroy a paused activity, exactly the same (low memory) reason as if it was stopped?
I think if an activity is paused because of an incoming phone call (which suddenly causes a low memory situation) the system simply prefers to release ressources of stopped activities. But how is that done? When does the system "kindly ask" the activity by calling finish() and when not, and when does onDestroy() still get called?
Most of what you asked is described pretty well by the documentation, but I think I can clarify a couple of things.
I'd like to know the difference
between the paused and stopped state.
Visibility. The two states are distinct because a paused activity may only be partially obscured by another activity such as one that's had the Dialog theme applied. That requires keeping whatever resources are needed to maintain visual state. Stopped activities can jettison those resources which could make the difference between the activity being destroyed or preserved if resources are tight.
I think ... the system simply prefers
to release ressources of stopped
activities. But how is that done?
It has to. Stopped activities are completely invisible, which makes them better candidates for killing than those that are still contributing something to what the user sees. I've never seen Android yank a paused-but-partially-visible activity out from under one that's resumed, but I suppose it could happen under the right circumstances. The system knows each activity's state because it's what's directing them there.
When does the system "kindly ask" the
activity by calling finish() and when
not, and when does onDestroy() still
get called?
The system will do orderly destruction when it can, but the API only guarantees are that an activity will ever see onPause() and onSaveInstanceState().
ETA: The exact reasons why activities are removed from the stack are in the source. You shouldn't depend on those reasons being universal truth, because there may be a future version of Android that makes its decisions differently.
Par for the course, I see! I see some valuable information, mixed with expensive misinformation. No, the online docs do NOT every specify exactly under what circumstances the process is killed. This is deliberate, since it is subject to change without notice. Sure, the most common reason for onDestroy() to be called is that the system is running out of memory, which is less common on newer phones (since they have so much memory). But there is no guarantee that that be the ONLY reason it is called.
But yes, the 'contract' between Android and the developers is that if you follow the rules, implementing the needed lifecycle callbacks when they are needed, then it will work, and you do not NEED to know exactly under what circumstances onStop(), onSaveInstanceState() and onDestroy() are called.
Now unlike Google, I will admit that the wording of the contract is somewhat vague at points. This is because, among other lesser reasons, they use terms that have a standard industry meaning, such as 'foreground', but they use them in slightly altered senses. And the alteration is either never explained or explained only in obscure places. It also doesn't help that the diagram purports to show "the paths an activity may take between states", yet fails to show that onDestroy() can be called at many times, even bypassing the transition from Resumed to Stopped. Yet the text clearly describes that possibility.
This is why, unfortunately, reading the Application Lifecycle section of "Application Fundamentals" is simply not enough. Instead, one must also read the Javadoc for EACH of the callbacks under that for Activity, and also the section of "Application Fundamentals" on Processes.
After that, it is enormously helpful to put Log.d statements in each of the callbacks and watch the logcat output while you cycle your application through the lifecycle. But even then, do not rely on lifecycle events taking place in the order you see in logcat unless you can find justification for it in one of these online docs mentioned above.