Restore saveInstanceState to Fragments onCreate method
I made a test application to see how to save InstanceState
.
We now have a main fragment activity and two tabs. I have a variable in Main Activity that it assigns in a method onCreate
.. and I would like to share it with snippets.
So, I created a public method in the main activity to call it inside fragments when I need the value of this variable. ((TMainActivity) getActivity()).getTestString()
The problem is the device is rotated. I got the default for the string, not the stored value.
And this is obvious because it onRestoreInstanceState
is called after the onCreate
fragments.
Now how can I fix this?
TMainActivity.java
public class TMainActivity extends FragmentActivity {
final private static String TAG = "TMainActivity";
final private static String EXTRA_TEST = "MAIN_KEY";
private CollectionPagerAdapter mCollectionPagerAdapter;
private ViewPager mainPager;
private String test = "Default";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v(TAG, "onCreate() Before test= " + test);
if (savedInstanceState == null) {
test = "New";
} else {
test = savedInstanceState.getString(EXTRA_TEST) + " - Restored";
}
Log.v(TAG, "onCreate() After test= " + test);
mainPager = (ViewPager) findViewById(R.id.main_pager);
mCollectionPagerAdapter = new CollectionPagerAdapter(getSupportFragmentManager());
mainPager.setAdapter(mCollectionPagerAdapter);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.v(TAG, "onSaveInstanceState()");
outState.putString(EXTRA_TEST, test);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.v(TAG, "onRestoreInstanceState()");
Log.v(TAG, "onRestoreInstanceState() savedInstanceState=" + (savedInstanceState != null));
test = savedInstanceState.getString(EXTRA_TEST);
}
public String getTestString() {
return test;
}
private class CollectionPagerAdapter extends FragmentStatePagerAdapter {
public CollectionPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int i) {
Fragment fragment = null;
switch (i) {
case 0:
fragment = new Tab1Fragment();
break;
case 1:
fragment = new Tab2Fragment();
break;
}
return fragment;
}
@Override
public int getCount() {
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
return "OBJECT " + (position + 1);
}
}
}
Tab1Fragment.java
public class Tab1Fragment extends Fragment {
final private static String TAG = "Tab1Fragment";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v(TAG, "onCreate()");
Log.v(TAG, "getTestString()=" + ((TMainActivity) getActivity()).getTestString());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main_tab1, container, false);
return rootView;
}
}
Tab2Fragment.java
public class Tab2Fragment extends Fragment {
final private static String TAG = "Tab2Fragment";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v(TAG, "onCreate()");
Log.v(TAG, "getTestString()=" + ((TMainActivity) getActivity()).getTestString());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main_tab2, container, false);
return rootView;
}
}
source to share
I had the same problem. First called onCreate
in Activity and in this method you already have access to this Bundle with your data. This means that you can restore the Activity and then use the data in a onCreateView
fragment that is called later.
Basically, you don't override the method onRestoreInstanceState()
, but rename it and call it from onCreate
within your activity. The reason not to override this method is because it will be called 2 times - from onCreate
you and then as part of the activity lifecycle. This will reset the value if it was changed in a Fragment.
In your case, you can simply move
Log.v(TAG, "getTestString()=" + ((TMainActivity) getActivity()).getTestString());
from onCreate
to onCreateView
.
This is not a good solution when you are recovering a large amount of data. Your UI thread would get stuck while restoring the Activity. But in this case, you can restore only part of the data that is needed in the Fragment, and restore the rest to onRestoreInstanceState
.
source to share