28

I have fragments I keep in the backstack of FragmentManager. Every fragment state is saved for orientation changes with member variables, like this for example:

@Override
public void onSaveInstanceState(Bundle outState) 
{
    super.onSaveInstanceState(outState);
    outState.putLong("userId", mUserId);
    outState.putString("username", mUsername);
}

My problem is that if there is an orientation change, since every fragment in the backstack gets called via onSaveInstanceState, I get a null pointer exception because the member variables don't exist anymore.

Any ideas on how to solve this?

Michael Eilers Smith
  • 8,466
  • 20
  • 71
  • 106
  • can you provide your logcat error message? – Vikram Gupta Apr 08 '13 at 07:31
  • onSaveInstanceState gets called before the actual change is applied, so your variables should exist when you call them, unless they're null because of other bugs in your code. Post some more code along with the error output form Logcat. – Shade Apr 10 '13 at 12:09
  • I can assure you my variables are fine. I think the problem is that my fragments in the backstack aren't getting onSaveInstanceState called when they are torn down; onSaveInstanceState is only called when the activity is destroyed, yet my variables don't exist anymore. So my current solution to that is: "if (mUserId != null && mUsername != null) ...". It ain't pretty, but it solves the problem. I find it weird to have an onSaveInstanceState method for fragments if it's not called when the fragment is torn down. – Michael Eilers Smith Apr 10 '13 at 16:07

4 Answers4

45

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 onRestoreInstanceState(Bundle inState){
    myFragment = getFragmentManager().getFragment(inState, "myfragment");
}

Tell me then if you had luck! :-)

Jorge Gil
  • 4,265
  • 5
  • 38
  • 57
7

Building on Jorge Gil - 'xɔɾ.xɛ xil answer Note the following:

  • Don't forget call the super implementations of onSaveInstanceState() and onRestoreInstanceState().
  • If you are using the support package: Please use getSupportFragmentManager() instead of getFragmentManager().
  • When retrieving your original fragment you got to cast it.

Sorry for being Captain obvious!

Sydwell
  • 4,954
  • 1
  • 33
  • 36
1

Does setting the setRetainInstance on the fragment help. try out

user2779311
  • 1,688
  • 4
  • 23
  • 31
0

I think the proper solution is to read those member variables out of savedInstanceState in onCreate which seems to be called always before onSaveInstanceState. If you process the fields in onViewCreated, they don't have the chance to get initialized before the next onSaveInstanceState (in this special case, when Fragment is in the backstack).

peter.bartos
  • 11,855
  • 3
  • 51
  • 62