Updated answer:
What are the scenarios where I might get in trouble?
When adding a Fragment
to the back stack and passing a Bundle
in the Fragment
from onSaveInstanceState()
to onCreateView()
on configuration change. Calling setRetainInstance(true)
will set the Bundle
to null on configuration change.
(I'm not sure a developer would actually attempt this since using setRetainInstance(true)
makes onSaveInstanceState()
kind of redundant, but I didn't see the behaviour documented in the API docs so I wrote up this answer).
If both addToBackStack()
and setRetainInstance(true)
are called, setRetainInstance()
partly alters the Fragment
lifecycle method calls and parameter values on configuration changes, compared to calling only addToBackStack()
.
Specifically, in the test below, looking a differences between calling only addToBackStack()
and calling setRetainInstance(true)
as well, and seeing what happens on configuration change:
Calling addToBackStack()
but not setRetainInstance(true)
;
onCreate()
and onDestroy()
are called.
- a bundle passed from
onSaveInstanceState()
is received as a parameter in onCreateView()
.
Calling both addToBackStack()
and setRetainInstance(true)
:
onCreate()
and onDestroy()
are not called. This is metioned in the API docs.
- a bundle passed from
onSaveInstanceState()
is not received in onCreateView()
. The passed-in Bundle
is null.
A test with logged method calls and parameters tested for null:
In the Activity
:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyFragment fragment;
if (savedInstanceState != null) {
fragment = (MyFragment) getFragmentManager().findFragmentByTag("my_fragment_tag");
} else {
fragment = new MyFragment();
FragmentTransaction t = getFragmentManager().beginTransaction();
t.addToBackStack(null);//toggle this
t.add(android.R.id.content, fragment, "my_fragment_tag").commit();
}
}
In the Fragment
:
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);//toggle this
}
and
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString("test", "value");
super.onSaveInstanceState(outState);
}
Test 1: Fragment lifecycle when addToBackStack()
is called , and setRetainInstance(true)
is not called
- onAttach()
- onCreate()
- onCreateView()
- onActivityCreated()
- onStart()
- onResume()
[Device rotated from portrait to landscape]
- onPause()
- onSaveInstanceState()
- onStop()
- onDestroyView()
- onDestroy()
- onDetach()
- onAttach()
- onCreate()
- onCreateView() with bundle param != null
- onStart()
- onResume()
Test 2 & 3: Fragment lifecycle calls with setRetainInstance(true)
called, addToBackStack()
called / not called (same result):
- onAttach()
- onCreateView()
- onActivityCreated()
- onStart()
- onResume()
[Device rotated from portrait to landscape]
- onPause()
- onSaveInstanceState()
- onStop()
- onDestroyView()
- onDetach()
- onAttach()
- onCreateView() with bundle param == null
- onStart()
- onResume()