问题
I have seen a few similar questions about onSaveInstanceState
not getting called for Fragment
s, but in my case Fragment
s work fine, it's the main FragmentActivity
that's having trouble.
The relevant code looks fairly simple:
public class MyFActivity extends FragmentActivity implements ActionBar.TabListener {
String[] allValues; // data to save
@Override
protected void onSaveInstanceState (Bundle outState) {
Log.d("putting it!", allValues.toString());
outState.putStringArray("allValues", allValues);
super.onSaveInstanceState(outState);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
allValues = savedInstanceState.getStringArray("allValues");
Log.d("getting it!", allValues.toString());
}
}
}
When pausing the activity (using the back button), the onSaveInstanceState
is never called, and consequently, savedInstanceState
is always null
within the onCreate
method upon resuming the app. I tried adding a block like this:
@Override
public void onPause() {
super.onPause();
onSaveInstanceState(new Bundle());
}
which was suggested in https://stackoverflow.com/a/14195202/362657 but while onSaveInstanceState
then gets called, savedInstanceState
remains null
within onCreate
method. What am I missing?
回答1:
The issue here is that you are misunderstanding how onSaveInstanceState
works. It is designed to save the state of the Activity
/Fragment
in the case that the OS needs to destroy it for memory reasons or configuration changes. This state is then passed back in onCreate
when the Activity
/Fragment
is returned to / restarted.
In a Fragment
, all of their lifecycle callbacks are directly tied to their parent Activity
. So onSaveInstanceState
gets called on the Fragment
when its parent Activity
has onSaveInstanceState
called.
When pausing the activity (using the back button), the onSaveInstanceState is never called, and consequently, savedInstanceState is always null within the onCreate method upon resuming the app.
When pressing back, the user is destroying the Activity
, and therefore its children Fragment
s, so there is no reason to call onSaveInstanceState
, since the instance is being destroyed. When you reopen the Activity
, it's a brand new instance, with no saved state, so the Bundle
passed in onCreate
is null
. This is behaving exactly as designed. However, try rotating the device or hitting the home button, then you will see the Activity
and its children Fragment
s have onSaveInstanceState
called, and passed back in onCreate
when returned to.
The hack you added, directly calling onSaveInstanceState(new Bundle());
inside of onPause
, is a very bad practice, as you should never call the lifecycle callbacks directly. Doing so can put your app into illegal states.
If what you really want is for your data to persist beyond an instance of your app, I suggest you look into using SharedPreferences or databases for more advanced data. You can then save your persistent data in onPause()
or whenever it changes.
Hope this helps.
回答2:
In an update to the accepted answer:
A fragment's onSaveInstanceState
may be called if you are using a ViewPager
with a FragmentStatePagerAdapter
(rather than FragmentPagerAdapter
)
FragmentStatePagerAdapter
This version of the pager is more useful when there are a large number of pages, working more like a list view. When pages are not visible to the user, their entire fragment may be destroyed, only keeping the saved state of that fragment. This allows the pager to hold on to much less memory associated with each visited page as compared to FragmentPagerAdapter at the cost of potentially more overhead when switching between pages.
And don't forget:
When using FragmentPagerAdapter the host ViewPager must have a valid ID set.
来源:https://stackoverflow.com/questions/15935322/fragmentactivity-onsaveinstancestate-not-getting-called