Using Onsaveinstancestate with Fragments in Backstack

Using onSaveInstanceState with fragments in backstack?

It is possible that your member variables don't exist anymore because the FragmentManager in your Activity is dying with all of your fragments.

You need to override the method onSaveInstanceState of your Activity class as well, because you need to save the Activity state before you save the Fragments state.

As the documentation says:

There are many situations where a fragment may be mostly torn down (such as when placed on the back stack with no UI showing), but its state will not be saved until its owning activity actually needs to save its state.

UPDATE

In your Activity onSaveInstanceState and onRestoreInstanceState, try saving you Fragment references and then restore them with something like this:

public void onSaveInstanceState(Bundle outState){
getFragmentManager().putFragment(outState, "myfragment", myfragment);
}
public void onRestoreInstanceState(Bundle inState){
myFragment = getFragmentManager().getFragment(inState, "myfragment");
}

Tell me then if you had luck! :-)

How to correctly save instance state of Fragments in back stack?

To correctly save the instance state of Fragment you should do the following:

1. In the fragment, save instance state by overriding onSaveInstanceState() and restore in onActivityCreated():

class MyFragment extends Fragment {

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
...
if (savedInstanceState != null) {
//Restore the fragment's state here
}
}
...
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);

//Save the fragment's state here
}

}

2. And important point, in the activity, you have to save the fragment's instance in onSaveInstanceState() and restore in onCreate().

class MyActivity extends Activity {

private MyFragment

public void onCreate(Bundle savedInstanceState) {
...
if (savedInstanceState != null) {
//Restore the fragment's instance
mMyFragment = getSupportFragmentManager().getFragment(savedInstanceState, "myFragmentName");
...
}
...
}

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

//Save the fragment's instance
getSupportFragmentManager().putFragment(outState, "myFragmentName", mMyFragment);
}

}

All fragments on backstack, have nulls in onSaveInstanceState, after rotation

I have exactly the same problem.
Lets say I have Frag A, calling Frag B
When I get from Frag A to Frag B, Frag A exists on backstack and is not showing. While in Frag B, on a first rotate the onSavedInstanceState() is being called for Frag A and it works fine, since the Frag A on back stack exists and all the data was there..
When I rotate the device again in Frag B, the Frag A onSavedInstanceState() is called again for some unknown reason.. between these calls a restore was never issued since onCreateView has not been called since Frag A is not visible.
Why it is doing that I have 0 clue.

What I do, is I check if Bundle is empty (and bundle does exist after 2nd rotate, its just empty) and if it is, I try to recreate Frag from scratch, which means reloading fresh data from a request... which is not the best solution..

Unable to save Fragment state with onSaveInstanceState

I solved it, the problem was here

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

if (savedInstanceState != null) {
dataFragment = (InputDataFragment) getSupportFragmentManager().getFragment(savedInstanceState, "dataFragment");
} else {
dataFragment = new InputDataFragment();
}

fragmentTransaction.add(R.id.container, dataFragment);
fragmentTransaction.commit();
}

When I'm in ResultsFragment and rotate the device, Activity onCreate method is called. Even though I got the previous InputDataFragment back from Bundle, calling FragmentTransaction.add() caused the loss of the data.

Moving FragmentTransaction code to the case where savedInstanceState == null was the solution.

Saving and restoring state using fragments

You want to save the value of your current checked state in onSaveInstanceState.

Something like this:

@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(CHECK_BOX_STATE, cb.getChecked());
}

and then when your view is created you want to get the value if it's present. And set your CheckBox state with it.

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fifth_layout, container, false);

cb = (CheckBox) view.findViewById(R.id.checkBox);
if (savedInstanceState != null) {
// Restore last state for checked position.
boolean checked = savedInstanceState.getBoolean(CHECK_BOX_STATE, false);
cb.setChecked(checked);
}

return view;
}

EDIT:

When you add the fragment, make sure to add it with a tag or id so that you can retrieve the same instance.

You could do a helper method to retrieve fragment and set the fragment.

private void setFragment(String tag, Fragment newFragment) {
FragmentManager fm = getSupportFragmentManager();
Fragment savedFragment = fm.getFragmentByTag(tag);
fm.replace(R.id.container, savedFragment != null ? savedFragment : newFragment, tag);
fm.commit();
}

so you your switch you can call the helper method instead.

switch (position) {
case 0:
setFragment("A", new FragmentA());
break;
....
}

Note: This is just an example not best practice since you are creating new fragments every time in your switch case now anyways. But it might point you in the right direction.



Related Topics



Leave a reply



Submit