In my FragmentActivity
I use several fragments. when configuration changed(on rotation) system destroys and re-creates each fragment.
I try to use this re-created fragments
mFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_frame);
and put it to new layout
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_frame, mFragment )
.commit();
but meet with strange behavior: several fragments are lost. they are not displayed on the screen more. in their place is empty.
Although the logs show that fragments are re-creates fine, but further shows that the fragment is again destroyed, again created and destroyed again.
I build test project for show problem more clearly and without husk.
and that demonstrable results (not enough reputation to insert pictures)
Activity started picture
Activity rotated picture
A,B,C,D is a fragments
As you can see after configuration changed some fragments are lost (B,D)
tell me what I'm doing wrong
here's the code to help (Edit:push code to gitHub in order to make it easier to try)
https:// github.com/nailgilaziev/TestFragmentsRetain
p/s sorry about links
here log cat after I rotate device
MainActivity: onPause Activity
MainActivity: onStop Activity
MainActivity: onDestroy Activity
A: onDestroyview
A: onDestroy
B: onDestroyview
B: onDestroy
C: onDestroyview
C: onDestroy
D: onDestroyview
D: onDestroy
MainActivity: onCreate Activity
A: onCreate
B: onCreate
C: onCreate
D: onCreate
MainActivity: replaced
MainActivity: onStart Activity
A: onCreateView
B: onCreateView
C: onCreateView
D: onCreateView
<--before this point all fine and then strange behavior began
for the lost fragments(B,D) are performed unnecessary calls-->
B: onDestroyview
B: onDestroy
D: onDestroyview
D: onDestroy
D: onCreate
D: onCreateView
MainActivity: onResume Activity
By breaking down your problem such that there are two Fragments instead of four, you will see that onCreateView
gets called multiple times on the same Fragment when orientation changes. This is an indication that the same Fragment is being added/created more than once.
Basically, when orientation changes, your Fragments will be re-attached automatically so there is no need to perform a FragmentTransaction
every time onCreate(Bundle)
is called.
What you should be doing in onCreate(Bundle)
instead is...
Null check the savedInstanceState
Bundle that is passed into onCreate(Bundle)
. -- If an orientation change occurs, onCreate(Bundle)
gets invoked again and the savedInstanceState
Bundle will become non-null. FragmentActivity
saves data in onSaveInstanceState(Bundle)
before it is re-created.
If savedInstanceState
is null, create your Fragments and attach them via FragmentTransaction
. Otherwise, do nothing.
In summary, your revised code should resemble the following...
FragmentManager fm = getSupportFragmentManager();
if(savedInstanceState == null) {
fm.beginTransaction()
.replace(R.id.a, new A())
.replace(R.id.b, new B())
.replace(R.id.c, new C())
.replace(R.id.d, new D())
.commit();
}
else {
a = fm.findFragmentById(R.id.a);
b = fm.findFragmentById(R.id.b);
c = fm.findFragmentById(R.id.c);
d = fm.findFragmentById(R.id.d);
}
Also, side note, the savedInstanceState
Bundle in the onCreate(Bundle)
method of a Fragment
will always be null, unless you save something to it in onSaveInstanceState(Bundle)
, so don't assume saveInstanceState
will also be non-null in a Fragment
when it is re-created, as it is in the case of a FragmentActivity
.