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);
}
Related
I implement the same fragment of 100 in ViewPager on my application. The fragment rather large display data from the server. When I put the code mViewPager.setOffscreenPageLimit (100), the app feels very heavy. Therefore, I use the way: remove setOffscreenPageLimit and invoke a method to check the data on the server and displays it when the fragment was selected. But when this happens: when Fragment "1" was chosen, then to fragment "2", back to fragment "1", Fragment "1" will repeat the activity. My question is how to keep the activity of each fragment is selected or when returning to the fragment that was selected at the last condition? Sorry for my English.
setOffscreenPageLimit : Set the number of pages that should be
retained to either side of the current page in the view hierarchy in
an idle state. Pages beyond this limit will be recreated from the
adapter when needed.
Don't setOffscreenPageLimit too large, because the view pager will keep the page active so your app will run slowly. And when you remove setOffscreenPageLimit, this setting defaults to 1. It means that pages beyond this limit (1) will be recreated from the adapter when needed.
https://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit(int)
if you remove setOffscreenPageLimit, The way to keep the activity of each fragment is store the state data of fragment in:
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putData("key", fragmentData);
}
when you leave it, when you back again, you update the fragment by the state data you have stored.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
fragmentData = savedInstanceState.getData("key", defaultData);
}
You should use some fragments in a viewpager, do not use too more. think about use a fragment and display many views, data in it.
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 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.
I have a fragment that loads data in the onResume/onCreate method and saves data in the onPause method. When I place this fragment in a viewpager it is initialized when it is the frament 1 left or 1 right to the current fragment shown on the screen.
During this time onResume is called and the fragment data is loaded. Which is fine.
However when the fragment is visible and the user swipes to another fragment no life cycle methods are called that I can find (onPause/ onStop/ onDetatch .. etc). The onPause/ onStop are only called when the fragment is 2 fragments left or 2 fragments right to the current one shown on the screen.
I would like to know how other people handle this, when do you save state in a Fragment which is shown in a ViewPager?
you can call this method to understand which fragment you are in
#Override
public void setMenuVisibility(final boolean visible) {
super.setMenuVisibility(visible);
if((visible) )
{
//do something here
}
}
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");
}
}
}