What exactly happens when you call setRetainInstance(true) on a Fragment? The documentation is virtually non-existent and this seems like a very important function. Specifically I want to know how much of this sequence (that I made up) is true:
- The user rotates the device.
- The fragment is detached from the
ActivityandFragment.onDetach()is called.- The activity is destroyed;
Activity.onDestroy()is called.- The
Activityjava object is deleted (when possible, by the GC).- A new
Activityjava object is created; its constructor, andonCreate()are called.- In
Activity.onCreate()we either havesetContentView(...)which sets a layout containing a fragment, or we useFragmentTransaction
to add a fragment.- I’m really not sure about this, but I assume that android is smart enough to find the old fragment, and call
Fragment.onAttach()to
reattach it to the newActivity- Next (or before? who knows?)
Activity.onResume()is called.
So is that correct? Is Android smart enough to find the old fragment, even if I explicitly use FragmentTransaction.add(new MyFragment(), ...) the first time? And if so, how do I avoid adding another fragment in onCreate()? Do I need to do something like this?:
if (getSupportFragmentManager().findFragmentByTag("foo") == null)
{
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(new FooFragment(), "foo").commit();
}
Ok, perhaps I was slightly too harsh on the Android documentation, because it does have some useful information, but sadly none of it is linked from
setRetainInstance(). From the page about fragmentsThis strongly implies that if you do
setContentView(R.layout.whatever)inActivity.onCreated()and that layout contains a fragment withsetRetainInstance(true), then when the activity is recreated it will be searched for again using its id or tag.Secondly, for UI-less fragments, it states
And the docs link to a very good example –
FragmentRetainInstance.javawhich I have reproduced below for your convenience. It does exactly what I speculated was the answer in my question (if (...findFragmentByTag() == null) { ...).Finally, I created my own test activity to see exactly what functions are called. It outputs this, when you start in portrait and rotate to landscape. The code is below.
(This is edited a bit to make it easier to read.)
Note that the Android documentation is wrong: the UI-less fragment does receive a call to
onCreateView()but it is free to returnnull.Source code for
TestActivity/TestFragmentSource code for
FragmentRetainInstance.java(as of API 16):