Fragment保存状态
http://stackoverflow.com/questions/11353075/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().
一种解决方式:
I guess there is an alternative way to achieve what you are looking for. I dont say its a complete solution but it served the purpose in my case.
What i did is instead of replacing the fragment i just added target fragment. So basically you will going to use add() method instead replace().
What else i did. I hide my current fragment and also add it to backstack.
Hence it overlaps new fragment over the current fragment without destroying its view.(check that its onDestroyView() method is not being called.Plus adding it to backstate gives me advantage of resuming the fragment.
Here is the code :
Fragment fragment=new DestinationFragment(); FragmentManager fragmentManager = getFragmentManager(); android.app.FragmentTransaction ft=fragmentManager.beginTransaction(); ft.add(R.id.content_frame, fragment); ft.hide(SourceFragment.this); ft.addToBackStack(SourceFragment.class.getName()); ft.commit();
AFAIK System only calls onCreateView if the view is destroyed or not created. But here we have saved the view by not removing it from memory.So it will not create new view.
And when you get back from Destination Fragment it will pop the last FragmetnTransaction removing top fragment which will make the topmost(SourceFragment's) view to appear over screen.
COMMENT :As i said it is not a complete solution as it doesnt remove the view of Source fragment and hence occupying more memory than usual.But still serve the purpose.Also we are using a totally different mechanism of hiding view instead of replacing it which is non traditional.
So its not really for how you maintain the state,but for how you maintain the view.
另外一种解决方式:
public final class MyFragment extends Fragment { private TextView vstup; private Bundle savedState = null; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.whatever, null); vstup = (TextView)v.findViewById(R.id.whatever); /* (...) */ /* If the Fragment was destroyed inbetween (screen rotation), we need to recover the savedState first */ /* However, if it was not, it stays in the instance from the last onDestroyView() and we don't want to overwrite it */ if(savedInstanceState != null && savedState == null) savedState = savedInstanceState.getBundle(App.STAV); if(savedState != null) vstup.setText(savedState.getCharSequence(App.VSTUP)); savedState = null; return v; } @Override public void onDestroyView() { super.onDestroyView(); savedState = saveState(); /* vstup defined here for sure */ vstup = null; } private Bundle saveState() { /* called either from onDestroyView() or onSaveInstanceState() */ Bundle state = new Bundle(); state.putCharSequence(App.VSTUP, vstup.getText()); return state; } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); /* If onDestroyView() is called first, we can use the previously savedState but we can't call saveState() anymore */ /* If onSaveInstanceState() is called first, we don't have savedState, so we need to call saveState() */ /* => (?:) operator inevitable! */ outState.putBundle(App.STAV, savedState != null ? savedState : saveState()); } /* (...) */ }
通过Activity保存Fragment状态
http://stackoverflow.com/questions/15608709/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 onRetoreInstanceState(Bundle inState){ myFragment = getFragmentManager().getFragment(inState,"myfragment"); }
Tell me then if you had luck! :-)
另外一种方式:
http://curioustechizen.blogspot.com/2014/02/nested-fragments-and-backstack-part-3.html
@Override public void onPause() { super.onPause(); ((NestedFragApp)getActivity().getApplication()).setFragmentSavedState(SAVED_STATE_KEY, getFragmentManager().saveFragmentInstanceState(this)); } @Override public void onDestroy() { super.onDestroy(); ((NestedFragApp)getActivity().getApplication()).setFragmentSavedState(SAVED_STATE_KEY, null); }
public static ContainerFragment newInstance(SavedState savedState) { ContainerFragment frag = new ContainerFragment(); frag.setInitialSavedState(savedState); return frag; } ... ... @Override public void onPause() { super.onPause(); ((NestedFragApp)getActivity().getApplication()).setFragmentSavedState(SAVED_STATE_KEY, getFragmentManager().saveFragmentInstanceState(this)); }