The Holo Dev
The Holo Dev

Reputation: 1016

Android fragment not saving state

I recently converted my app from an activity based app to a fragment based app. It's a score keeping app, and I was easily able to save and restore score when it was an activity. However, that doesn't seem to be working as a fragment. Here's my code:

 @Override
public void onSaveInstanceState(Bundle savedInstanceState){
    super.onSaveInstanceState(savedInstanceState);

    if(t!=null&&flag==1){
        savedInstanceState.putInt("time", t.getTimeLeft());
    } else {
        savedInstanceState.putInt("time", 0);
    }

    savedInstanceState.putIntArray("score_array", points);
    savedInstanceState.putIntArray("position_array", spinnerPosition);
    savedInstanceState.putBooleanArray("checked_array", shouldBeChecked);

    flag = 0;
    Log.d("MyApp", "savingState");
}

@Override
public void onActivityCreated(Bundle savedInstanceState){
    super.onActivityCreated(savedInstanceState);

    Log.d("MyApp", "onActivityCreated");

    try {
        int timeLeft = savedInstanceState.getInt("time");

        points = savedInstanceState.getIntArray("score_array").clone();
        spinnerPosition = savedInstanceState.getIntArray("position_array").clone();
        shouldBeChecked = savedInstanceState.getBooleanArray("checked_array").clone();

        ((BaseAdapter) ((ListView)getView().findViewById(R.id.missionList)).getAdapter()).notifyDataSetChanged();

        if(timeLeft!=0){
            flag=1;

            this.getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

            t = new TimerClass(timeLeft*1000, 1000);
            t.setViews((TextView)getView().findViewById(R.id.minuteView), (TextView)getView().findViewById(R.id.tenSecondView), (TextView)getView().findViewById(R.id.secondView), (Button)getView().findViewById(R.id.start_button));
            ((Button)getView().findViewById(R.id.start_button)).setText(R.string.stop);
            t.start();
        }
    } catch (Exception e) {
        e.printStackTrace();
    } 

}

I used this exact same code successfully on an activity in onRestoreInstanceState rather than onActivityCreated and without the try/catch. The problem is I'm getting null pointer errors an time I try and pull something from the bundle. I can see saving state in the log, and then onActivityCreated, but onActivityCreated doesn't seem to be getting the stuff put in the bundle by onSavedInstanceState. I just get a null pointer on every line that calls savedInstanceState.getAnything(). However, from my reading, onCreate, onCreateView, and onActivityCreated all use the same bundle. I have tried moving the code to the other two with no luck.

Upvotes: 6

Views: 4302

Answers (2)

Saba Sanatgar
Saba Sanatgar

Reputation: 21

For anyone who needs a better answer:

Always test for if(savedInstanceState!=null) before accessing it, to avoid null pointer errors. Also, be aware that onSaveInstanceState() won't be able to save your data in all cases when your fragment is destroyed.

Particularly if your Fragment is pushed onto the back stack, and the device is rotated. In this case, only onDestoryView() gets called when your Fragment is pushed onto the back stack, so when onSaveInstanceState() runs during device rotation, it won't be able to save any data from your Views because they were all destroyed earlier.

See the following thread for a work-around. I think it's useful for everybody developing with Fragments. Especially DroidT's answer: https://stackoverflow.com/a/19744402/2517350

Upvotes: 1

The Holo Dev
The Holo Dev

Reputation: 1016

I ended up coming up with a fairly hacky work around. Not thrilled with it, since it's not actually solving the core problem. If anyone can help me find that, I'd happy accept that answer over this.

That said, I simply used the activity's onSaveInstanceState and onRestoreInstanceState to save and restore the fragment data.

Upvotes: 0

Related Questions