Considering this scenario: If I created an activity and it moves to the background and this activity contains a Fragment
which is set to setRetainInstance(true)
then the Android OS might at some point still decide to shut down the activity's hosting process in order to free memory.
Then the Activity
's state is saved via onSaveInstanceState(Bundle)
where - as far as I understood - the related Bundle
is written and to the file system to survive the process shut down. (thus the requirement of objects in the bundle being Serializable
). Later, the applications state can be retrieved in a new process via onRestoreInstanceState(Bundle)
.
In contrast, my Fragment
is allowed to contain variables which are not necessarily Serializable
. Therefore, I figured, the Fragment
cannot be stored on disk like the Bundle
is. So what happens to my fragment when the process gets killed?
I was wondering about this reading the developer's guide (http://developer.android.com/guide/components/processes-and-threads.html):
A process holding an activity that's not currently visible to the user (the activity's onStop() method has been called). These processes have no direct impact on the user experience, and the system can kill them at any time to reclaim memory for a foreground, visible, or service process. Usually there are many background processes running, so they are kept in an LRU (least recently used) list to ensure that the process with the activity that was most recently seen by the user is the last to be killed. If an activity implements its lifecycle methods correctly, and saves its current state, killing its process will not have a visible effect on the user experience, because when the user navigates back to the activity, the activity restores all of its visible state.
I understood the above killing such that the VM instance is shut down and the state of the process is written to the file system (here comes the Bundle
into play). Later the bundles are read for resuming the process. Since the retaining of fragments is not concerned with life cycle methods and since I would not know how to retain e.g. a pointer to a network connection (you should of course never have such a pointer in a fragment anyhow), I was wondering if the fragments are still restored if the process is shut down in the meantime. I concluded that they surely needed to be recreated and that the life cycle methods are therefore to be preferred over setRetainInstance(true)
whenever possible.
Does this assumption make any sense?
SetRetainInstance(true) allows the fragment sort of survive. Its members will be retained during configuration change like rotation. But it still may be killed when the activity is killed in the background.
setRetainInstance(true); // Start up the worker thread. mThread.start(); } /** * This is called when the Fragment's Activity is ready to go, after * its content view has been installed; it is called both after * the initial fragment creation and after the fragment is re-attached * to a new activity.
Retained fragments take advantage of the fact that a fragment's view can be destroyed and recreated without having to destroy the fragment itself. During a configuration change, the FragmentManager first destroys the views of the fragments in its list.
Sounds like you're mixing up two concepts here.
setRetainInstance()
for a Fragment
then that means it will fully stay in memory and not be re-created only for configuration changes. A similar mechanism is available for Activity
objects but they need to explicitly define an Object
which is going to be saved. This works via Activity.onRetainNonConfigurationInstance()
, not via onSaveInstanceStae()
.Activity
/Fragment
is destroyed (which happens independently of its hosting Process
, btw). This works via Activity.onSaveInstanceState()
and Fragment.onSaveInstanceState()
.Regarding your questions.
Activity
. It can contain non-serializable objects which can be saved across config changes as described above.Hope I could contribute to clarifying this a bit.
Edit after your first comment.
Regarding the comment:
onRetainNonConfigurationInstance
is deprecated": Yes. I mentioned it for demonstration purposes because of a specific wording in your question. Also, with Android 2 devices having a 46% market share as per today (official Google figures), this method will definitely stay around for a very long time, deprecated or not.setRetainInstanceState
in the case of config changes. (But note that this relates to the Instance, in other words, the full object.)Regarding your edit:
Fragment
's Bundle
will be stored and restored to/from the Bundle
regardless of setRetainInstanceState
if you use Fragment.onSaveInstanceState()
for this purpose, for everything that makes sense.visibility
attribute will not be saved. Whether that's supposed to be a bug or a feature I don't know, but it's a fact. But this is only a side remark; UI elements will save most of their relevant state.Bundle
and actually implement saving their state will be saved in a Bundle
, this means that you must provide such information yourself if you want your Fragment
to save some state information. Also, again: No, this does not only relate to killing the process but also to deleting Activity
and Fragment
objects which are not visible; like the last Activity shown -- the Process
may well stay alive.Bundle
will be read to pass it to the re-construction of Activity and/or Fragment objects, there is nothing done automatically in this process (except library objects which save their state also restore their state), but Android does not "resume" the "Process" from these Bundle
s.Fragment
is only performed upon configuration changes _IF_ you request it via setRetainInstance
, but we're mostly talking about the re-creation of Fragment
objects from a Bundle
here, which does involve the life cycle methods as documented by Google.setRetainInstance
) because when that happens, everything is simply kept in memory. Also, even if your Fragment
gets deleted (because it became invisible) and your process is still there (because it shows the next Activity), you can (and should) keep references to objects which are expensive to re-create, such as a network connection, in your Application
object, which exists as long as your process lives (more or less). It is only when your whole app is killed by Android that you lose everything, but the serialization we're discussing happens much more often.Your conclusion:
I concluded that they surely needed to be recreated and that the life cycle methods are therefore to be preferred over setRetainInstance(true) whenever possible. Does this assumption make any sense?
Unfortunately not, since you are mixing up completely independent concepts.
I'll give it a final try:
Application
object because it would be a lousy user experience if you created it from scratch on a regular basis throughout your app.Application
object will only die if Android kills your app.Activity
and Fragment
objects will be deleted from your app regularly when the user moves forward within your app.Activity
and Fragment
objects from Bundle
s using lifecycle methods. Saving something in a Bundle makes sense if you have expensive computations to do to re-create the internal state. You can live without the Bundle
mechanism because Android will always save the Intent
so if you don't do anything then you'll start without saved state.Activity
life cycle methods get involvwed and it's up to your implementation to use the saved data effectively. For Fragment
s, this is where setRetainInstance' comes into play: Your
Fragment` will survive the config change in memory if you set it.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With