In my application I have to handle different situations which need a lot of fragments to be instantiated.
To maintain the user experience more fluently, I manage a Fragment's BackStack and sometimes a child fragment's backstack too.
Everything works fine until the user has filled part of this backstack.
Now, in case the user want to go in a fragment which was previously added to backstack, the system handle the request Pop Fragments out until the one the user request.
In this way, the newInstance() method of the fragment is not called because (I believe) the fragment is recovered from memory.
Here's the problem:
Sometimes, in my app, in different places, I create instances of the same fragment, but passing different parameters inside Fragment.newInstance();
In this way i can use the same fragment in different ways.
But, If the same fragment has already been instantiated, the system recovers the old fragment instance from the BackStack.
Real situation:
Fragment A --> My fragment;
Instance A1 ----> Instance i got from newInstance(Parameter 1);
Instance A2 ----> Instance i got from newInstance(Parameter 2);
In the app there is a DrawerMenu with 2 voices, the first one call and show A1 and the second one call and show A2.
The user open the app, then click on the first voice, then A1 is showed in the correct way.
Than the user click on the second voice, A.newInstance(Parameter 2); is called, but the system recover A1 from backstack and A1 is showed instead of A2.
Thanks.
EDIT:
My Transaction code for FragmentManager, this method stay in the MainActivity.
When i want to change fragment, I call changeFragment(FragmentA.newIstance(Parameter1),true,true);
the boolean paramenters are for the backstack, and for the animation
public void changeFragment(Fragment frag, boolean saveInBackstack, boolean animate) {
String backStateName = ((Object) frag).getClass().getName();
String TAG ="Fragment manager";
try {
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate(backStateName, 0);
if (!fragmentPopped && manager.findFragmentByTag(backStateName) == null) {
//fragment not in back stack, create it.
FragmentTransaction transaction = manager.beginTransaction();
if (animate) {
Log.d(TAG, "Change Fragment: animate");
transaction.setCustomAnimations(R.anim.fadein,R.anim.fadeout, R.anim.fadein,R.anim.fadeout);
}
transaction.replace(R.id.framelayout_container, frag, backStateName);
if (saveInBackstack) {
Log.d(TAG, "Change Fragment: addToBackTack " + backStateName);
transaction.addToBackStack(backStateName);
} else {
Log.d(TAG, "Change Fragment: NO addToBackTack");
}
transaction.commit();
} else {
// AnimationShake(findViewById(R.id.fragment_holder));
}
} catch (IllegalStateException exception) {
Log.w(TAG, "Unable to commit fragment, could be activity as been killed in background. " + exception.toString());
}
}
This is the Method for ChildFragmentManager, I use it inside fragments which should handle other child fragments inside them, I call it in the same way of the on before:
public void changeFragmentChild(Fragment frag, boolean saveInBackstack, boolean animate) {
String backStateName = ((Object) frag).getClass().getName();
String TAG ="Fragment manager";
try {
FragmentManager manager = getChildFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate(backStateName, 0);
if (!fragmentPopped && manager.findFragmentByTag(backStateName) == null) {
//fragment not in back stack, create it.
FragmentTransaction transaction = manager.beginTransaction();
if (animate) {
Log.d(TAG, "Change Fragment: animate");
transaction.setCustomAnimations(R.anim.enter_from_right,R.anim.exit_from_left, R.anim.enter_from_left,R.anim.exit_from_right);
}
transaction.replace(R.id.chilcontainer, frag, backStateName);
if (saveInBackstack) {
Log.d(TAG, "Change Fragment: addToBackTack " + backStateName);
transaction.addToBackStack(backStateName);
} else {
Log.d(TAG, "Change Fragment: NO addToBackTack");
}
transaction.commit();
} else {
// AnimationShake(findViewById(R.id.fragment_holder));
}
} catch (IllegalStateException exception) {
Log.w(TAG, "Unable to commit fragment, could be activity as been killed in background. " + exception.toString());
}
}