Current, I have 2 Fragments
, which is switch-able through ActionBar
's tab.
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); ActionBar.Tab newTab = getSupportActionBar().newTab(); newTab.setText("history"); newTab.setTabListener(new TabListenerHistoryFragment>(this, "history", HistoryFragment.class));
@Override public void onTabSelected(Tab tab, FragmentTransaction ft) { // Check if the fragment is already initialized if (mFragment == null) { // If not, instantiate and add it to the activity mFragment = Fragment.instantiate(mActivity, mClass.getName()); mFragment.setRetainInstance(true); ft.add(android.R.id.content, mFragment, mTag); } else { // If it exists, simply attach it in order to show it ft.attach(mFragment); } }
I realize the first time of my Activity
(This activity is holding 2 fragments) being launched, Fragment
s' methods will be called in the following sequence.
onCreate -> onCreateView -> onStart
When I perform Tab switching, and then Tab switching back to the same Fragment, the following methods will be called again.
onCreateView -> onStart
I just wish to retain the same GUI view state, when Tab is being switched back.
I know that I can save/restore simple variables using the following method when Tab switching
android fragment- How to save states of views in a fragment when another fragment is pushed on top of it
But, that is not something I want, as my GUI state is pretty difficult to describe within whole bunch of primitive values.
I try the following approach. Of course it won't work, as I am getting the following runtime error.
public class HistoryFragment extends Fragment { View view = null; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (this.view != null) { return this.view; } this.view = inflater.inflate(R.layout.history_activity, container, false); } }
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
I realize the following demo example is able to preserve its fragment GUI state (For instance, the position of vertical scroll of list) when there is Tab switching. But I guess, perhaps it is because they are using ListFragment? As I do not find they perform any special handling to preserve GUI state.
May I know, how I can avoid from recreating same view when perform tab switching?
FragmentManager is the class responsible for performing actions on your app's fragments, such as adding, removing, or replacing them, and adding them to the back stack.
Android OS provides a back stack function for Activity, it also provides the back stack function for Fragment. If you add one Fragment into the back stack, when you press the android device back menu, you can find the Fragment that is saved in the back stack popup.
oncreate view instantiates the view, onviewcreated is called after oncreateview and before saved states are restored... it's more a timing issue in the lifecycle of the fragment. – me_ Oct 23, 2018 at 5:57.
I had the same problem, and tried to follow the suggestion in the error message. I tried the following code, and it worked for me.
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) { if (mMyView == null) { mMyView = new MyView(getActivity()); } else { ((ViewGroup) mMyView.getParent()).removeView(mMyView); } return mPuzzleView; }
I started searching for a simple solution for this many hours ago and finally stumbled across the answer by @roger which saved me lots of hair....
When using the ViewPager in other implementations, I could simply call:
mViewPager.setOffscreenPageLimit(//number of pages to cache);
So, I was very surprised it took me so many hours to resolve this. The example he gave wasn't entirely clear though, so for the sake of completeness, here is the code I use for the Fragments in my FragmentTabHost
import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class FragmentExample extends Fragment { private View rootView; public FragmentExample() { } @Override public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { if (rootView == null) { rootView = inflater.inflate(R.layout.fragment_example_layout, container, false); // Initialise your layout here } else { ((ViewGroup) rootView.getParent()).removeView(rootView); } return rootView; } }
I searched for the following key phrases which I'm adding here, in the hope that I may save someone else from the frustration I've just experienced!
FragmentTabHost save Fragment state
FragmentTabHost views recreated
FragmentTabHost cache Fragments
FragmentTabHost onCreateView Fragment destroyed
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With