I have a parent Fragment Activity that has a ViewPager which contains a child ViewPager. The child ViewPager contains Fragments for each page. I communicate between these child page fragments and the top parent Fragment Activity using a callback interface e.g.
public interface Callbacks {
public void onItemSelected(Link link);
}
In the parent Fragment Activity I listen for onItemSelected
events e.g.
@Override
public void onItemSelected(Link link) {
Bundle argumentsFront = new Bundle();
argumentsFront.putParcelable(FragmentComments.ARG_ITEM_ID, link);
fragmentComments = new FragmentComments();
fragmentComments.setArguments(argumentsFront);
getSupportFragmentManager().beginTransaction().replace(R.id.post_container, fragmentComments).commitAllowingStateLoss();
}
Now this works fine when the app is first launched.
If you turn the device to change the orientation the Activity restarts. All fragments reinitialise themselves as I use setRetainInstance(true);
(I do not call setRetainInstance(true) in the page Fragments of the child ViewPager as it is not supported). However if I click a list item in the Fragment of the child ViewPager I get this exception:
FATAL EXCEPTION: main
java.lang.IllegalStateException: Activity has been destroyed
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1342)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:578)
Does anyone know why this happens?
Thanks
When you rotate the device, Android saves, destroys, and recreates your Activity
and its ViewPager
of Fragments
. Since the ViewPager
uses the FragmentManager
of your Activity
, it saves and reuses those Fragments
for you (and does not create new ones), so they will hold the old references to your (now destroyed) original Activity
, and you get that IllegalStateException
.
In your child Fragments
, try something like this:
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.v(TAG, "onAttach");
// Check if parent activity implements our callback interface
if (activity != null) {
try {
mParentCallback = (Callbacks) activity;
}
catch (ClassCastException e) {
}
}
}
Then when a selection occurs:
if(mParentCallback != null) {
mParentCallback.onItemSelected(selectedLink);
}
Since onAttach
gets called as part of the Fragment
lifecycle, your Fragments
will update their callback reference on rotation.