I seem to have the opposite problem to everyone else. :)
My onSaveInstanceState is getting called whenever I navigate from one activity to the next.
I checked in LogCat and it is definitely NOT killing the activity.
Also, I see that the onRestoreInstanceState is not called when returning so it must have still been in memory.
I thought it was only called when freeing up memory or during orientation changes.
Yes, onSaveInstanceState() is called when the activity is paused. This is because once the activity is paused, Android can kill the process at any time time (without calling any other lifecycle methods). If the activity is resumed before the process is killed, Android realizes that it doesn't need to call onRestoreInstanceState() so it doesn't make that call (this is an optimization).
What about the doc saying;
"If called, this method will occur before onStop(). There are no guarantees about whether it will occur before or after onPause()."
Related
I'm testing that my app is able to recover from unexpected situations that lead the OS to kill my app's process due to different circumstances like low memory. To do this, I've enabled "Don't Keep Activities" in Developer Options.
I'm attempting to restore the app's state by saving state values in the Activity's Bundle through the lifecycle method onSaveInstanceState, but after setting breakpoints I've noticed that onSaveInstanceState does not get called.
Question:
Am I wrong in expecting onSaveInstanceState to be called in this scenario or might there be other factors that are preventing the method to fire? If neither, what else can I do to recover the state in this scenario?
I think two possibilities are supposed.
Your scenario is wrong
The official reference says:
Do not confuse this method with activity lifecycle callbacks such as
onPause(), which is always called when the user no longer actively
interacts with an activity, or onStop() which is called when activity
becomes invisible. One example of when onPause() and onStop() is
called and not this method is when a user navigates back from activity
B to activity A: there is no need to call onSaveInstanceState(Bundle)
on B because that particular instance will never be restored, so the
system avoids calling it. An example when onPause() is called and not
onSaveInstanceState(Bundle) is when activity B is launched in front of
activity A: the system may avoid calling onSaveInstanceState(Bundle)
on activity A if it isn't killed during the lifetime of B since the
state of the user interface of A will stay intact.
If your scenario is a 'no need to call' case, onSaveInstanceState won't be called.
Your breakpoints are wrong
If called, this method will occur after onStop() for applications
targeting platforms starting with Build.VERSION_CODES.P. For
applications targeting earlier platform versions this method will
occur before onStop() and there are no guarantees about whether it
will occur before or after onPause().
So the timing of onSaveInstanceState called depends on your targeting platform.
An easy workaround is to backup data with SharedPreference, etc. in onPause.
Android documentation about Activity says that onDestroy may not get called if the system kills your process to reclaim memory.
My questions are
Is there a way (developer tool etc) to simulate this situation (no onDestroy) for testing?
Suppose my process is killed by the system to reclaim memory and user navigates back to my activity, what methods are called? Does onCreate get called again?
onDestroy simply isn't guaranteed to be called. In both situations everything has to be created again... so onCreate, onStart etc. You don't need a tool - if its some code that MUST run, don't put it there. https://developer.android.com/reference/android/app/Activity.html#onDestroy%28%29
I have an activity and I have a fragment stack in it and sometimes, this stack get's lost... Although I save and restore it...
I know following:
onSaveInstanceState is not called:
a) if the user navigates back, which makes sense...
b) if the activity is finished
onSaveInstanceState is called:
a) on screen rotation
I discovered through debugging, that I can't be sure, if onSaveInstanceState is called, if screen turns black...
My app is an app, that you use for logging, meaning, you put your phone aside and come back every now and then and fill out your log... So sometimes, my activity is recreated with an empty bundle and onSaveInstanceState was not called, although my app was in the foreground and only the screen turned off...
Questions
1) what can I do to solve that problem? Do I really have to save my fragment states and the stack persistantly?
2) on screen rotation, I can be SURE that onSaveInstanceState is called, can I? Are there any other circumstances, where I can rely on onSaveInstanceState?
1) Im reffering to this thread: android life cycle you should use onPause() because you can't be sure if the app is just paused or beeing killed.
2) from developer.android.com ( Activity)
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.
I'm confused why anyone would ever override Activity.onDestroy() instead of onPause() if according to the documentation:
There are situations where the system will simply kill the activity's
hosting process without calling this method (or any others) in it,
I see much code that overrides onDestroy() despite this warning. Why?
Why override Activity.onDestroy() if it isn't reliably called?
It's not that it isn't reliably called... it's just that it isn't the only way the Activity can be killed. The Android system might trash your entire process without giving the ActivityManager the chance to call onDestroy() if your device begins to lack memory resources.
For this reason, you shouldn't ever rely on onDestroy() being called, and you should always save persistent state in onPause.
Objects held by the activity will get destroyed if the process is killed directly. If the process is not killed (and onDestroy() is called) then you will have to manually release the objects if needed. E.g, when the process is killed, a Cursor will be destroyed, but if the process is not destroyed and you repeatedly enter the activity there will be resource leakage.
I know I can use isFinishing() in onPause() to know whether an activity is going to be killed by finish().
Then, how can I know an activity is going to be killed by OS temporarily due to low memory?
Thanks.
Per the docs, onDestroy should be called right before the Activity is destroyed, regardless of the reason. If the finish was requested, isFinishing will return true. So if it is false, you can assume that the system needed to finish.
However, as the docs also say
Note: do not count on this method
being called as a place for saving
data!
In general, you cannot guarantee that your Activity will be killed nicely. Things like task killers mess with the lifecycle.
Use onPause or onSaveInstanceState to save things properly.
You cannot.
It's possible your activity could go away without the rest of your app going way, in this case onDestroy would be called. However it's also possible that your whole app is going to get killed at once, this like a kill -9 in unix. Your app cannot run any code at this time, it's killed instantly and without warning.
To handle this properly, you want to design your app to save all vital information to disk in onPause and be ready to retrieve it later in onCreate if needed.