Search code examples
androidandroid-fragmentsandroid-savedstatefragment-lifecycle

Fragment saves previous state but it doesn't restore correctly


I have an actviity which loads a fragment in the onCreate like this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    loadFragment(new FragmentName());
}

private void loadFragment(Fragment fragment) {
    FragmentManager fm = getFragmentManager();
    FragmentTransaction fragmentTransaction = fm.beginTransaction();
    // replace the FrameLayout with new Fragment
    fragmentTransaction.replace(R.id.frag_lay, fragment);
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commit();
}

And I'm trying to save and restore the state of the fragment loaded like this:

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

    if (savedInstanceState != null) {
        spinner.setSelection(savedInstanceState.getInt("spinner"));
    }
}

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

    outState.putInt("spinner", spinner.getSelectedItemPosition());
}

What happens is that I'm correctly storing the position of my spinner, but the spinner gets recreated anyway and its position is the default one, even though I'm selecting the saved one. I'm not really sure why this happens, can anybody help?

EDIT

I'm setting up the spinner here:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    view = inflater.inflate(R.layout.fragment_campus, container, false);

    ...
    setupSpinner();
    return view;
}

private void setupSpinner() {
    ArrayAdapter<CharSequence> adapter = 
              ArrayAdapter.createFromResource(this.getActivity(),
                        R.array.array_spinner, 
                            android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter)
}

EDIT 2

I did some more tries. I put some toasts to display what was happening like this:

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

    if (savedInstanceState != null) {
        Toast toast = Toast.makeText(getActivity(), "saved !=", Toast.LENGTH_SHORT);
        toast.show();
    }else{
        Toast toast = Toast.makeText(getActivity(), "saved ==", Toast.LENGTH_SHORT);
        toast.show();
    }
}

When I tried to run this code on the emulator this happens: when I first launch the app it goes in the else statement (which should be right). When I change orientation both toasts are displayed (obviously I first saved something in the onSaveInstanceState), and this is not right. Why is this happening?


Solution

  • Change this line in your activity:

    loadFragment(new FragmentName());
    

    to this:

    if (savedInstanceState == null) {
        loadFragment(new FragmentName());
    }
    

    The FragmentManager will automatically save and restore fragments in your activity for you, as part of the same process that saves and restores the state of those fragments. Right now, however, every time your activity is recreated, you throw away the old fragment and replace it with a new one.