Why isn't my fragments onSaveInstanceState() being called?

I have a fragment which has its own state (selected buttons, etc). That state is lost on a screen rotation.

The activity that contains the fragment has a portrait layout in /res/layout/, and an almost identical landscape layout in /res/layout-land/. Both layouts include the fragment like so:

  • Is there a way in Android to tell if a users device has an actual keyboard or not?
  • Where is the layout file of my settings activity?
  • How do I get Google refund orders ?
  • Android - FFmpeg Alternative to get video frames. (Due to licensing)
  • Android OCR Library
  • “Package not signed correctly” appearing for some users
  • <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <fragment
            android:id="@+id/testFragment"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            class="au.com.x.y.TestFragment" />
    ...</LinearLayout>
    

    The fragment class I’ve been testing with is:

    public class TestFragment extends android.support.v4.app.Fragment {
        private static final String TAG = "TestFragment";
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.i(TAG, "onCreate(): " + 
                    (savedInstanceState != null ? "NOT NULL" : "NULL"));
        }
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            Log.i(TAG, "onActivityCreated(): " + 
                    (savedInstanceState != null ? "NOT NULL" : "NULL"));
        }
        public void onSaveInstanceState(Bundle state) {
            super.onSaveInstanceState(state);
            Log.i(TAG, "onSaveInstanceState()");
            state.putString("saved_thing", "some_value");
        }
        public View onCreateView(
            LayoutInflater inflater,
            ViewGroup container,
            Bundle b) { ... }
    }
    

    Note that I’m using the pre-3.0 support package for fragments, brought in through ActionBarSherlock.

    LogCat gives me:

    BEFORE SCREEN ROTATION (PORTRAIT):
    02-23 11:45:58.015: I/TestFragment(22629): onCreate(): NULL
    02-23 11:45:58.015: I/TestFragment(22629): onCreateView()
    02-23 11:45:58.035: I/TestFragment(22629): onActivityCreated(): NULL
    AFTER SCREEN ROTATION (LANDSCAPE):
    02-23 11:46:00.615: I/TestFragment(22629): onCreate(): NULL
    02-23 11:46:00.615: I/TestFragment(22629): onCreateView()
    02-23 11:46:00.635: I/TestFragment(22629): onActivityCreated(): NULL
    

    As you can see, onSaveInstanceState() is never called, and the fragment always gets a null savedInstanceState, in both onCreate() and onActivityCreated().

    I’ve tried myFragment.setRetainInstance(true) in my activities onCreate(), but that hasn’t changed anything.

    My onSaveInstanceState() has an @Override, so I know it’s not something stupid like a typo.

    I’ve looked at one of the ActionBarSherlock examples (com.actionbarsherlock.sample.shakespeare) and the fragments there are having their onSaveInstanceState() methods called properly. As far as I can tell, that example is written exactly how my code is — fragments included through both a layout and a layout-land XML. I’ve even built that sample using exactly the same version of ActionBarSherlock as my main project is using, and saving the instance state works fine for that example.

    How do I retain my fragments state across screen rotations? Why isn’t onSaveInstanceState() being called?

    Related posts:

    Inheritance and extension of XML (menu) resources
    How can I load a Google Play app in the Android emulator?
    XmlPullParser getAttributeValue returns null
    Detect 7 inch and 10 inch tablet programmatically
    Overlapping hidden fragments after application gets killed and restored
    Are asserts available on Android?
  • ListView nested scrolling on API<21
  • Android Volley : ImageRequest deprecated
  • Is there an easy way to “deactivate logging” prior to releasing your app on the market?
  • TranslateAnimated ImageView not clickable after animation
  • Zoom in Animation
  • Implementing JKalman on Android
  • 2 Solutions collect form web for “Why isn't my fragments onSaveInstanceState() being called?”

    You can enable myFragment.setRetainInstance(true) to retain the state, but it does this ‘automatically’, i.e. it retains the values assigned to your class members and does NOT use the onSaveInstanceState (and hence savedInstanceState is always null).

    Make sure the FragmentActivity that hosts this fragment does not override onSaveInstanceState or when it does it should call super.onSaveInstanceState(Bundle).

    If the fragment needs a different layout resource when rotated, setRetainInstance(true) cannot be used. This page shows the lifecycle of fragment with setRetainInstance(true).

    Original idea is use onSaveInstanceState() to retain all members data, just like a regular Activity. However, for some reason, onSaveInstanceState() is not get called. But FragmentActivity is correct, as @Eric Kok suggested). The best solution I found is to use Arguments of Fragment.

    See the solution by Fyodor Volchyok, it is simple. Just work as if the outState in onSaveInstanceState(), and savedInstanceState in onViewCreated().

    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.