I have a fragment
(let's call it MyFragment) that inflates different layouts according to a parameter passed in the arguments.
All works well if MyFragment is started from a different fragment. But if MyFragment is active and I want to launch a new MyFragment with a different layout parameter, the fragmentManager
does not create a new fragment at all.
data.setInt("Layout index",i);
fragmentTab0 = (Fragment) new MyFragment();
fragmentTab0.setArguments(data);
fragmentTransaction.replace(R.id.fragmentContent, fragmentTab0, "MY");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
How can I force convince the fragmentTransaction
to launch the fragment again?
NOTE: The important point here is I need to inflate again a layout, which is different from the layout inflated before. The code looks like:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
switch( getArguments().getInt("Layout index") ) {
case 1:
rootView = inflater.inflate(R.layout.firstlayout, container, false);
break;
case 2:
rootView = inflater.inflate(R.layout.secondlayout, container, false);
break;
case 3:
rootView = inflater.inflate(R.layout.thirdlayout, container, false);
break;
default: break;
}
Bypass Solution
Explanation (hoover to see it)
Since the source code for. Thanks to @devconsole for pointing out the source code. I know now why this happens. ThefragmentTransaction.replace/add/remove
is not available I could not find what really happens. But it is reasonable to think that at some point it compares the current class name with the replacement class name and it exits if they are the same.FragmentManager.removeFragment()
method does not reset the fragment state, it remains RESUMED, then the methodmoveToState(CREATED)
only initilizes a fragmentif (f.mState < newState)
=if (RESUMED < CREATED)
=false
. Else, ergo, it just resumes the fragment.
So to solve this problem I created an almost empty fragment which only purpose is to replace itself with the target fragment.
public class JumpFragment {
public JumpFragment() {
}
@Override
public void onStart() {
Bundle data = getArguments();
int containerId = data.getString("containerID");
String tag = data.getString("tag");
//Class<?> c = data.get???("class");
//Fragment f = (Fragment) c.newInstance();
Fragment f = (Fragment) new MyFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
f.setArguments(data);
fragmentTransaction.replace(containerId, f, tag);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
And I use it:
data.setInt("Layout index",i);
data.setInt("containerID",R.id.fragmentContent);
data.setString("tag","MY");
fragmentTab0 = (Fragment) new JumpFragment();
fragmentTab0.setArguments(data);
fragmentTransaction.replace(R.id.fragmentContent, fragmentTab0);
fragmentTransaction.commit();
Now no fragment is replaced by a same class fragment:
MyFragment -> JumpFragment -> MyFragment
I haven't figured out how to pass the class through the arguments bundle, to make it totally generic.