How to keep the same fragment when activity restar

2020-06-04 09:13发布

问题:

I found many post explaining how get the Fragment from the savedInstanceState Bundle but, because the Activity can swap between 4 Fragments, i need a way to know which Fragment was alive before rotate when the orientation started to change.

The reason i have several Fragments is because i am using Navigation Drawer, so each menu item as a fragment.

回答1:

I had the same issue and I fixed it adding this to the Navigation Drawer activity code:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if(savedInstanceState==null){
        //Handle the initial fragment transaction
    }
    ...
}

For example, I have a navigation drawer with "Home", "Settings" and "About" as menu items, each with a fragment "home_fragment", "settings_fragment" and "about_fragment".

If I want "home_fragment" to appear when the navigation drawer activity launches, I use this code on the OnCreate function:

FragmentManager fM = getSupportFragmentManager();
fM.beginTransaction().replace(R.id.NavDrawContent,new home_fragment()).commit();

But I want it to execute only when (savedInstanceState == null), so that when we change the phone orientation while in settings_fragment (for example), it doesn't inflate home_fragment.

So the final code (inside the navigation drawer activity OnCreate):

super.onCreate(savedInstanceState);
if(savedInstanceState==null){
    FragmentManager fM = getSupportFragmentManager();
    fM.beginTransaction().replace(R.id.NavDrawContent,new home_fragment()).commit();
}


回答2:

In the activity, you save the fragment's instance in onSaveInstanceState() and restore in onCreate().

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    if (savedInstanceState != null) {     
        fragment = getSupportFragmentManager().getFragment(savedInstanceState, "KEY");
        changeFragment(fragment, "MY TAG")
    } else {
        setupFragment();
    }
    ...
}


@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    Fragment fragment = getSupportFragmentManager().findFragmentByTag("MY TAG");
    if (fragment != null) {
        getSupportFragmentManager().putFragment(outState, "KEY", fragment);
    }
}

If you need to know which fragment was saved, you can check with instanceof, for example:

if (fragment instanceof SettingsFragment) {
    // ...
}


回答3:

Found my own answer and it it was a really simple thing after all. I left the solution here for those who are not familiar to android,like me .

//current fragment
int fragment_id;

//make fragment selection available form the menu resource id
private void setFragment(MenuItem item) {

    Fragment fragment = null;
    fragment_id = item.getItemId();

    switch (fragment_id) {
        case R.id.nav_option_1:
            fragment = MyFragment1.newInstance(true);
            break;
        ...
        //Set fragment
        FragmentTransaction t = getSupportFragmentManager().beginTransaction();
        t.replace(R.id.content_navigation, fragment);
        t.commit();
    }

    item.setChecked(true);
}

private class DrawerItemClickListener implements NavigationView.OnNavigationItemSelectedListener {

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        setFragment(item);
        return false;
    }
}

//save the state
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(SAVE_INSTANCE_FRAGMENT_KEY, fragmentid);
}

//restore the saved fragment on create
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_navigation);
    ///...
    if (savedInstanceState != null) {
        int fragment_id = savedInstanceState.getInt(SAVE_INSTANCE_FRAGMENT_KEY);
        selectItem(mDrawerList.getMenu().findItem(fragment_id));
    } else {
        selectItem(mDrawerList.getMenu().findItem(R.id.home_fragment_id));
    }

}