Replacing a fragment with another fragment of the same class

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 fragmentTransaction.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.. Thanks to @devconsole for pointing out the source code. I know now why this happens. The FragmentManager.removeFragment() method does not reset the fragment state, it remains RESUMED, then the method moveToState(CREATED) only initilizes a fragment if (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.


The following worked without problems for me. Notice that I used the Android Support Library.

activity_main.xml :

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/button_one"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ONE" />

    <Button
        android:id="@+id/button_two"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/button_one"
        android:text="TWO" />

    <FrameLayout
        android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/button_one" >
    </FrameLayout>

</RelativeLayout>

MainActivity.java :

public class MainActivity extends FragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            Fragment fragment = DetailsFragment.newInstance("INITIAL");
            transaction.add(R.id.main_container, fragment);
            transaction.commit();
        }

        findViewById(R.id.button_one).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                update("Button 1 clicked");
            }
        });

        findViewById(R.id.button_two).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                update("Button 2 clicked");
            }
        });
    }

    protected void update(String value) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        Fragment fragment = DetailsFragment.newInstance(value);
        transaction.replace(R.id.main_container, fragment);
        transaction.commit();
    }

    public static final class DetailsFragment extends Fragment {
        public static DetailsFragment newInstance(String param) {
            DetailsFragment fragment = new DetailsFragment();
            Bundle args = new Bundle();
            args.putString("param", param);
            fragment.setArguments(args);
            return fragment;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            TextView textView = new TextView(container.getContext());
            textView.setText(getArguments().getString("param"));
            return textView;
        }
    }
}

Did you try to first remove your fragment with remove(fragMgr.findFragmentByTag("MY")) and then add the new one ? PS : I assume you don't keep any reference to this fragment.

链接地址: http://www.djcxy.com/p/14290.html

上一篇: 追踪int []的分配

下一篇: 用同一类的另一个片段替换片段