Understanding Fragment's setRetainInstance(boolean)

AndroidAndroid Fragments

Android Problem Overview

Starting with the documentation:

> public void setRetainInstance (boolean retain) > > Control whether a fragment instance is retained across Activity re-creation (such as from a configuration change). This can only be used with fragments not in the back stack. If set, the fragment lifecycle will be slightly different when an activity is recreated: > > - onDestroy() will not be called (but onDetach() still will be, because the fragment is being detached from its current activity). >- onCreate(Bundle) will not be called since the fragment is not being re-created. >- onAttach(Activity) and onActivityCreated(Bundle) will still be called.

I have some questions:

  • Does the fragment also retain its view, or will this be recreated on configuration change? What exactly does "retained" mean?

  • Will the fragment be destroyed when the user leaves the activity?

  • Why doesn't it work with fragments on the back stack?

  • Which are the use cases where it makes sense to use this method?

Android Solutions

Solution 1 - Android

First of all, check out my post on retained Fragments. It might help.

Now to answer your questions:

> Does the fragment also retain its view state, or will this be recreated on configuration change - what exactly is "retained"?

Yes, the Fragment's state will be retained across the configuration change. Specifically, "retained" means that the fragment will not be destroyed on configuration changes. That is, the Fragment will be retained even if the configuration change causes the underlying Activity to be destroyed.

> Will the fragment be destroyed when the user leaves the activity?

Just like Activitys, Fragments may be destroyed by the system when memory resources are low. Whether you have your fragments retain their instance state across configuration changes will have no effect on whether or not the system will destroy the Fragments once you leave the Activity. If you leave the Activity (i.e. by pressing the home button), the Fragments may or may not be destroyed. If you leave the Activity by pressing the back button (thus, calling finish() and effectively destroying the Activity), all of the Activitys attached Fragments will also be destroyed.

> Why doesn't it work with fragments on the back stack?

There are probably multiple reasons why it's not supported, but the most obvious reason to me is that the Activity holds a reference to the FragmentManager, and the FragmentManager manages the backstack. That is, no matter if you choose to retain your Fragments or not, the Activity (and thus the FragmentManager's backstack) will be destroyed on a configuration change. Another reason why it might not work is because things might get tricky if both retained fragments and non-retained fragments were allowed to exist on the same backstack.

> Which are the use cases where it makes sense to use this method?

Retained fragments can be quite useful for propagating state information — especially thread management — across activity instances. For example, a fragment can serve as a host for an instance of Thread or AsyncTask, managing its operation. See my blog post on this topic for more information.

In general, I would treat it similarly to using onConfigurationChanged with an Activity... don't use it as a bandaid just because you are too lazy to implement/handle an orientation change correctly. Only use it when you need to.

Solution 2 - Android

setRetaininstance is only useful when your activity is destroyed and recreated due to a configuration change because the instances are saved during a call to onRetainNonConfigurationInstance. That is, if you rotate the device, the retained fragments will remain there(they're not destroyed and recreated.) but when the runtime kills the activity to reclaim resources, nothing is left. When you press back button and exit the activity, everything is destroyed.

Usually I use this function to saved orientation changing Time.Say I have download a bunch of Bitmaps from server and each one is 1MB, when the user accidentally rotate his device, I certainly don't want to do all the download work again.So I create a Fragment holding my bitmaps and add it to the manager and call setRetainInstance,all the Bitmaps are still there even if the screen orientation changes.

Solution 3 - Android

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. If the containing activity in the background is killed by the system, it's instanceState should be saved by the system you handled onSaveInstanceState properly. In another word the onSaveInstanceState will always be called. Though onCreateView won't be called if SetRetainInstance is true and fragment/activity is not killed yet, it still will be called if it's killed and being tried to be brought back.

Here are some analysis of the android activity/fragment hope it helps. http://ideaventure.blogspot.com.au/2014/01/android-activityfragment-life-cycle.html

Solution 4 - Android

setRetainInstance() - Deprecated

As Fragments Version 1.3.0-alpha01

> The setRetainInstance() method on Fragments has been deprecated. With > the introduction of ViewModels, developers have a specific API for > retaining state that can be associated with Activities, Fragments, and > Navigation graphs. This allows developers to use a normal, not > retained Fragment and keep the specific state they want retained > separate, avoiding a common source of leaks while maintaining the > useful properties of a single creation and destruction of the retained > state (namely, the constructor of the ViewModel and the onCleared() > callback it receives).

Solution 5 - Android

setRetainInstance(boolean) is useful when you want to have some component which is not tied to Activity lifecycle. This technique is used for example by rxloader to "handle Android's activity lifecyle for rxjava's Observable" (which I've found here).


All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionUserView Question on Stackoverflow
Solution 1 - AndroidAlex LockwoodView Answer on Stackoverflow
Solution 2 - AndroidsuitianshiView Answer on Stackoverflow
Solution 3 - AndroidKejun XiaView Answer on Stackoverflow
Solution 4 - AndroidGastón SaillénView Answer on Stackoverflow
Solution 5 - AndroidMarian PaździochView Answer on Stackoverflow