Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

<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?

like image 804
George Avatar asked Feb 23 '12 00:02

George


People also ask

What is the purpose of using onSaveInstanceState () here?

As your activity begins to stop, the system calls the onSaveInstanceState() method so your activity can save state information to an instance state bundle.

Can I use onCreate in fragment?

Fragment has many methods which can be overridden to plug into the lifecycle (similar to an Activity): onAttach() is called when a fragment is connected to an activity. onCreate() is called to do initial creation of the fragment. onCreateView() is called by Android once the Fragment should inflate a view.

How do you save an instance state in fragment?

The first key is that we can save our Fragments' state ourselves using FragmentManager. saveInstanceState(Fragment) . Before removing the Fragment, call this method to get a Bundle containing your Fragment's saved state! The second key is restoring state.


1 Answers

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).

like image 110
Eric Kok Avatar answered Oct 14 '22 13:10

Eric Kok