I have a nested Fragment that I am trying to restore the state given an orientation change.
So firstly my setup is as follows:
Activity -> ParentFragment (SetRetainInstance(true)) -> ChildFragment
In My Child fragment I have the onSaveInstance code as follows:
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Serialize the current dropdown position.
outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActivity().getActionBar()
.getSelectedNavigationIndex());
}
However when I orientate the device in all the LifeCycle events return a savedInstance state of null.
Am I doing this incorrectly for a ChildFragment? Why is my state not getting saved and returned?
It's due to setRetainInstance(true) of your parent fragment. Android retains a fragment with all its children fragments. So your ChildFragment is not destroyed, and that's why you get null in savedInstanceState. The documentation of onCreateView states:
savedInstanceState If non-null, this fragment is being re-constructed from a previous saved state as given here.
You can try to comment setRetainInstance(true) out and ensure you get correct value for savedInstanceState.
Related
I have doubt in fragment system.
I have two fragments like A and B
If i move A to B,
Navigation.findNavController(v).navigate(R.id.B)
Now A fragment onDestroyView is called i know it's normal.
After in B Fragment i called PopBackStack
Navigation.findNavController(v).popBackStack()
now A fragment onViewCreated is called i also know it's normal.
Now A fragment all ui is initial state.
My question is how to keep A fragment UI State like recyclerview scroll position, FAB button visibility, etc
You have to store recyclerview scroll position, FAB button visibility in a variable and set those values after onViewCreated is called.
OR
You can store it in Bundle of onSaveInstanceState and retain its state
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
I have a Fragment F attached on Activity A. When another activity becomes front-activity it is called onSaveInstanceState. I've overrided that function and it looks like:
public void onSaveInstanceState(Bundle outState){
saveState_to_outstate
}
Now, when the Fragment F is front again it is called onViewCreated(View view, Bundle savedInstanceState). I would like to restore previously saved state but I cannot because savedInstanceState is null though it was written before in onSaveInstanceState.
Why it happened?
If you want to restore Fragment F with previous Data. As according to my knowledge you should perform inside onViewStateRestored() method of Fragment.
OnViewStateRestored (Bundle) tells the fragment that all of the saved state of its view hierarchy has been restored.
you Should visit this link for your reference:Fragment
Method A: You can pass the data from Activity A to Fragment F by bundle or intent. it's similar to usage of saving instance.
Send data from activity to fragment in android
MethodB: You can only use following function with onCreate() at the same place, either fragment F or Activity A.
public void onSaveInstanceState(Bundle outState){
outState.putInt("STATE_NAME", 123);//123 is the data you gonna save
super.onSaveInstanceState(outState);//Don't forget to put this
}
MethodC: Use hardcode-like SharePreference Android Shared preferences example ,it's also like the bundle and intent, and it won't be effected by Activity or fragment life periods.
I have an activity that would have fragments dynamically added using the method below.
FragmentTransaction transaction=getSupportFragmentManager().beginTransaction();
FragmentA fragmentA = new FragmentA();
transaction.add(R.id.fragment_container, fragmentA, "fragmentA");
transaction.addToBackStack("fragmentA");
transaction.commit();
FragmentA has a TextView. I have a navigation drawer on my activity and want to switch between fragments (for example FragmentA, FragmentB, and FragmentC) depending on which item was clicked in the navigation drawer. How do I save the state of the fragments when changing to another fragment. I've implemented onSavedInstance(Bundle outState) and onActivityCreated(Bundle savedInstanceState) but savedInstanceState is always null. I want to be able to save the fields of FragmentA when changing from FragmentB and then changing back to FragmentA from FragmentB.
I cannot save the state when pressing the backstack. It seems like the fields are not being saved.
What are the correct ways to do this?
Fragment's onSaveInstanceState(Bundle outState) will never be called unless fragment's activity call it on itself and attached fragments. Thus this method won't be called until something (typically rotation) force activity to SaveInstanceState and restore it later.
So In on createView you can do something like that
.
.
.
Bundle mySavedInstanceState = getArguments();
String value = mySavedInstanceState.getString(KEY);
.
.
Save value in onPause() method
#Override
public void onPause() {
super.onPause();
String value = //get value from view;
getArguments().putString(KEY, value);
}
You can use SharePrefrences to save Data in FragmentA and read it when it is called again. Additional advantage is that the Data saved in SharePreferences can be read in other fragments if need be.
Useful Links on Fragments;
- https://developer.android.com/training/basics/fragments/index.html
-http://www.vogella.com/tutorials/AndroidFragments/article.html
I found a quick way to maintain the state of each fragment at the below link.
How do I restore a previously displayed Fragment?
I didn't realize that FragmentTransaction had a hide() method to hide the view of the current fragment and a show() method to show it again.
I have Fragment which I replace by another one. I put transaction to backstack so I can move back later. If I press back button saveInstanceState Bundle of restored Fragment is null in it's methods cause saveInstanceState method of Fragment is actually called when parent Activity instance destroyed. So how I must restore Fragment state after returning it from backstack?
This problem was mostly related to ListViews. I have found a solution in more correct managing of adapter data. I had local mAdapter variable in my Fragment which was created, populated with data and set to ListView in onResume() method of my Fragment. I have found solution in moving this code into onActivityCreated() method.
I am really confused with the internal state of a Fragment.
I have an Activity holding only one Fragment at once and replaces it, if another Fragment should get shown. From the docs onSaveInstanceState is called ONLY if the Activitys onSaveInstanceState is getting called (which isn't called in my case).
If I stop my Fragment, I'll store its state myself inside a Singleton (yeah, I know I hate Singletons, too, but wasn't my idea to do so).
So I have to recreate the whole ViewHirarchy, create new Views (by using the keyword new), restore its state and return them in onCreateView.
I also have a Checkbox inside this View from which I explicitly do NOT want to store its state.
However the FragmentManager wants to be "intelligent" and calls onViewStateRestored with a Bundle I never created myself, and "restores" the state of the old CheckBox and applies it to my NEW CheckBox. This throws up so many questions:
Can I control the bundle from onViewStateRestored?
How does the FragmentManager take the state of a (probably garbage-collected) CheckBox and applies it to the new one?
Why does it only save the state of the Checkbox (Not of TextViews??)
So to sum it up: How does onViewStateRestored work?
Note I'm using Fragmentv4, so no API > 17 required for onViewStateRestored
Well, sometimes fragments can get a little confusing, but after a while you will get used to them, and learn that they are your friends after all.
If on the onCreate() method of your fragment, you do: setRetainInstance(true); The visible state of your views will be kept, otherwise it won't.
Suppose a fragment called "f" of class F, its lifecycle would go like this:
- When instantiating/attaching/showing it, those are the f's methods that are called, in this order:
F.newInstance();
F();
F.onCreate();
F.onCreateView();
F.onViewStateRestored;
F.onResume();
At this point, your fragment will be visible on the screen.
Assume, that the device is rotated, therefore, the fragment information must be preserved, this is the flow of events triggered by the rotation:
F.onSaveInstanceState(); //save your info, before the fragment is destroyed, HERE YOU CAN CONTROL THE SAVED BUNDLE, CHECK EXAMPLE BELLOW.
F.onDestroyView(); //destroy any extra allocations your have made
//here starts f's restore process
F.onCreateView(); //f's view will be recreated
F.onViewStateRestored(); //load your info and restore the state of f's view
F.onResume(); //this method is called when your fragment is restoring its focus, sometimes you will need to insert some code here.
//store the information using the correct types, according to your variables.
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("foo", this.foo);
outState.putBoolean("bar", true);
}
#Override
public void onViewStateRestored(Bundle inState) {
super.onViewStateRestored(inState);
if(inState!=null) {
if (inState.getBoolean("bar", false)) {
this.foo = (ArrayList<HashMap<String, Double>>) inState.getSerializable("foo");
}
}
}