38

I have a fragment attached to the activity using XML (and setContentView() in activity). A have a problem because I have very dynamic views in my fragment, so when orientation changes I must restore all states of views.

I have problem because I'm using something like that:

public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean("restore", true);
        outState.putInt("nAndroids", 2);
   }

But after orientation change when methods with param Bundle savedInstanceState are called (like onCreateView etc) my savedInstanceState is always null.

I'm not a noob in the Android but now I'm very angry because of this problem...

public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    if (savedInstanceState == null) {
        //smth
    } else {
        // smthelse THIS IS NEVER REACHED BECAUSE BUNDLE IS ALWAYS NULL
    }

    getListView().setDivider(getResources().getDrawable(R.drawable.list_divider));
}
TommyNecessary
  • 1,377
  • 1
  • 13
  • 19

6 Answers6

65

All the problem was in that I don't declare android:id for the fragment in XML. Android needs ID or TAG to recognize stored fragment and reproduce all elements in it. So guys, remember - every instance of fragment needs unique id or tag!

Also, when setRetainInstance(true) is declared then bundle should always return null.

TommyNecessary
  • 1,377
  • 1
  • 13
  • 19
  • 9
    Can you show how your code looks? Not sure how/where you are hooking the xml ID up to your fragment activity. – Azurespot Mar 23 '15 at 21:21
  • setRetainInstance(true) is handy when you want to retain state of your fragment, however this can be tricky with nested fragments, such as when storing states within a ViewPager via FragmentPagerAdapter. – worked Nov 25 '15 at 18:15
  • 3
    can you please clarify how to specify fragment id in xml. – babay Dec 21 '15 at 23:41
  • 2
    @babay: it's simple: – TommyNecessary Dec 22 '15 at 09:51
  • 13
    Thank you. but what about dynamically added fragments (added with FragmentManager transactions) ? The only way I've found is to store state in Fragment's arguments... – babay Dec 22 '15 at 19:45
  • 2
    How do I deal with this when I am using Fragment via ViewPager – Neon Warge Dec 07 '16 at 03:39
  • 4
    Answering @babay question about the programmatically / dynamically added Fragments, I had same problem: each time I tried to recover the standard savedInstanceState it was always null. The reason is because I was using popBackStack, so the onSaveInstanceState method is never called as it goes after onDestroy but not after onDestroyView, so for this reason the savedInstanceState is always null in the Fragment. So the solution is simple: create a private Bundle that you can save state of the View in the onPause and then you recover it back in onCreateView. – Javi Sep 14 '18 at 18:41
7

I had a similar problem where I was always getting savedInstanceState as null inspite of supplying the bundle to the Fragment.

The only solution that worked for me was to do

myFragment.setArguments(bundle) 

with my bundle from the Activity and do a

Bundle bundle = this.getArguments();

in onCreateView of the fragment.

Hope this helps someone else.

Arun Yogannadan
  • 139
  • 1
  • 7
  • 8
    WTF, savedInstanceState will always return null if u will set arguments from activity. Activity bundle has nothing to do with the savedInstanceState bundle. – Rakesh Yadav May 25 '17 at 06:37
2

For Fragment :-

use this for save state of fragment on orientation.

onCreate(Bundle save)
{
   super.onCreate(save);
   setRetainInstance(true);
}

See this tutorial :- http://techbandhu.wordpress.com/2013/07/02/android-headless-fragment/

For Activity:-

When you start your application, in onCreate, your bundle object is null, so you have to put a check like below and when you rotate your screen then onSaveInstance is called and your bundle object is initialized

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

    if (savedInstanceState != null) {
         boolean t = outState.getBoolean("restore"); 
         int s = outState.getInt("nAndroids");
    }
}
Mars
  • 4,197
  • 11
  • 39
  • 63
Rahul Gupta
  • 5,275
  • 8
  • 35
  • 66
  • 1
    I understand this but I haven't this problem in activity instance. When I'm doing sth like you I have a good values from bundle, but in the same case in fragment i have savedInstanceState null even I put values in onSavedInstanceState method in fragment instance. – TommyNecessary Dec 12 '13 at 17:39
1

Ok I know this is an old post but I couldn't find the right answer for me here nor many other places, so I am posting how I fixed my case.

So My Fragment is inside an Activity. And I originally tried to save Bundle only in Fragment and retrieve it at onCreateView. However that was the problem.

I fixed this by initiating myFragment object in activity and put that object to activity Bundle at onSaveInstanceState(). Then retrieved it at onRestoreInstanceState(). I used getSupportFragmentManager().putFragment/getFragment. Then the savedInstanceState in fragment was no longer null.

  • 1
    I have same kind problems with navGraph fragments. At onSaveInstanceState() onSaveInstanceState() is not null. but at onCreate it is and onRestoreInstanceState() is not called at all. – Reijo Korhonen Mar 05 '23 at 01:03
1

First you should put your data, then call super.onSaveInstanceState(outState);

public void onSaveInstanceState(Bundle outState) {

    outState.putBoolean("restore", true);
    outState.putInt("nAndroids", 2);
    super.onSaveInstanceState(outState);
}

And be sure that activity has not nohistory property in AndroidManifest.xml or set it to false.

        <activity
        android:noHistory="false">
1

If you are trying to use outState to save the state and destroy the fragment by navigating to another fragment, it will not work, you have in this case to save your state permanently in either sharedPreferences or if it's big and you want to be more organized you can use any persistence lib like Room, Realm, ...etc.

When should use outState and savedInstanceState only to make Fargment/Activity survive config change(rotation for example) or processes being killed by the OS when the app is in background for example.

Mohammad Elsayed
  • 1,885
  • 1
  • 20
  • 46