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);
}
}
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.
How to save state in fragment
Instead of restoring the state during onCreate()
you may choose to implement onRestoreInstanceState()
, which the system calls after the onStart()
method. The system calls onRestoreInstanceState()
only if there is a saved state to restore, so you do not need to check whether the Bundle
is null.
FYI : this is a sample code. Just for your reference.
public class MainFragment extends Fragment {
private String title;
private double rating;
private int year;
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString(TITLE, "Gladiator");
savedInstanceState.putDouble(RATING, 8.5);
savedInstanceState.putInt(YEAR, 2000);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
title = savedInstanceState.getString(TITLE);
rating = savedInstanceState.getDouble(RATING);
year = savedInstanceState.getInt(YEAR);
}
}
FYI : This really a good thread check this also Once for all, how to correctly save instance state of Fragments in back stack?
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.
How can I maintain fragment state when added to the back stack?
If you return to a fragment from the back stack it does not re-create the fragment but re-uses the same instance and starts with onCreateView()
in the fragment lifecycle, see Fragment lifecycle.
So if you want to store state you should use instance variables and not rely on onSaveInstanceState()
.
Android Fragment not saving UI State on pressing Back Button
Is there any particular reason why you are replacing the fragment? If not, you can just simply add it instead of replacing and that will ensure the state gets maintained.
Your code will change like this
.add(R.id.container, SecondFragment.newInstance())
.addToBackStack(null)
.commit()
Related Topics
How to Connect to Android With Adb Over Tcp
How to Connect to a Specific Wi-Fi Network in Android Programmatically
How to Execute Dex: Method Id Not in [0, 0Xffff]: 65536
How to Change Fontfamily of Textview in Android
"Default Activity Not Found" on Android Studio Upgrade
Your Content Must Have a Listview Whose Id Attribute Is 'Android.R.Id.List'
Download Binary File from Okhttp
Android How to Use Mediascannerconnection Scanfile
Building and Running App Via Gradle and Android Studio Is Slower Than Via Eclipse
How to Make an Imageview With Rounded Corners
Open Another Application from Your Own (Intent)
Best Practice For Storing and Protecting Private API Keys in Applications
How to Run a Runnable Thread in Android At Defined Intervals
Can the Android Drawable Directory Contain Subdirectories