I add my views programmatically.How i can restore states of my views after the fragment is killed ?
I think it can be done with `onViewStateRestored, but i can not configure it's properly.
How i can do it in a right way?
No matter how do you creating views (programmatically or in layout file). Save current fragment state in onSaveInstanceState() and restore it in onCreateView().
See the onSaveInstanceState() reference for further details.
Related
In my app I'm using the Jetpack navigation component and I have an issue with fragment state not being saved when navigating back to a fragment.
When I navigate from MainFragment to SettingsFragment it's via the overflow menu:
NavigationUI.onNavDestinationSelected(item, Navigation.findNavController(view));
When navigating back to MainFragment, the visibility on some views and text in some TextViews is not saved, and my state machine variable has lost its state as well.
I've read solutions where the root view is saved in a global variable in the fragment, and while this solves the visibility issue on views, the TextViews are still empty and the state machine variable is reset.
Is there a proper way to make sure fragment state is saved in this case?
If you're using view model then it can save state for you. However, that only works for simple views. For complex views including some custom views that you created, make sure that you have assigned a unique id to those as Android uses those ids to recover their state. You can use generateViewId() method on View to do so. Worst case, you might need to implement onSavedInstanceState and onRestoreInstanceState on your views.
Also, make sure you have not set to setRetainInstance to false in the xml or code.
While doing that please make sure you use parcelize annotation for your parcelable data models as this can save you a lot of time.
I hope your problem is solved by assigning unique IDs and you don't have to deal with saving state. Good luck!
I have an android app in which I want to dynamically add and remove Fragments to a ViewPager during runtime, and preserving the Fragments on configuration changes.
Thus far I have implemented a FragmentStatePagerAdapter, holding my Fragments in a list with methods add, remove and replace to manipulate my Fragments. Basically, all they do is insert or delete a Fragment in the list and then call notifyDatasetChanged(). I insert the staring Fragment as a new Fragment during the Activitys onCreate() method.
I know want to preserve my Fragments during configuration changes. Currently, when I change my screen orientation, all my currently Fragments are deleted, and I get back to the starting Fragment, naturally because the Activity is recreated, and the Fragment and the Adapater are reinstantiated during the onCreate() call. I was trying to save the state of the Adapter with the Adapter.saveInstance() during the Activitys onPause(), but when I try to restore it via Adapter.restoreInstance(), I get an empty adapter.
Can anyone give me a hint on what is the correct way in Android to save state a FragmentStatePagerAdapter?
To save the state of the current fragment, i think first of all you will have to check which fragment is currently added/visible in the container activity. Once you have that fragment, simply use onSaveInstanceState() method of the container activity to save the instance of the current fragment.
For code snippet please follow this link.
When using FragmentActivity it automatically restores fragment state and recreates all fragments.
I know this is done mainly saving the state in onSaveInstanceState and then restored in activity's onCreate. Looking a little on the code I've seen that all fragments are recreated (or only attached if retainInstance is true) and added to the FragmentManager but it's not clear to me in which way they are added to the view, because view isn't automatically restored.
My original problems were that I get duplicates of some fragments similar to that other question.
I workarrounded that in onCreate with:
Fragment f = fm.findFragmentByTag(tagName);
if(f==null) {
f = createFragment();
fm.beginTransaction().add(R.id.myContainer,f,tagName).commit();
} else {
//Nothing it's on the view
}
Now it works, but I still doesn't understand completely how it works.
My doubts are:
In which moment and how are fragments attached to the View? I've experimented that fragment restoration is done in onCreate of FragmentActivity. But if I call setContentView after that, how the fragment attach to the view?
Can I prevent fragment recreation without overwriting onSaveInstanceState? Because due to different orientation layouts with different number of fragments my original intention was to recreate only one state fragment marked as retained an don't restore the other view fragments that are not marked as retained.
View hierarchy in not restored automatically. So, in Fragment.onCreateView() or Activity.onCreate(), you have to restore all views (from xml or programmatically). Each ViewGroup that contains a fragment, must have the same ID as when you created it the first time. Once the view hierarchy is created, Android restores all fragments and put theirs views in the right ViewGroup thanks to the ID. Let say that Android remembers the ID of the ViewGroup on which a fragment was.
This happens somewhere between onCreateView() and onStart().
I think it could be possible to keep fragment recreation but, on the ViewGroup that hold the fragment, set visibility to GONE. In this way, the fragment doesn't appear and you can remove it programmatically later.
I have a simple chat app where a RelativeLayout with multiple views is created for each message. After the activity is stopped or destroyed all of my added layouts disappear from the parent so all messages are gone.
Sure I could put the ID (along with other values) of each single view into a SharedPreferences object or a database to restore all messages after the activity is re-created.. but is there a simpler way to save the dynamically created layouts..? The parent is defined by XML.
When an Activity (or a Fragment) becomes invisible - its View hierarchy gets destroyed, and you can't overcome that. In fact, you don't need too. The solution is to store the messages inside a database and recreate the View hierarchy on Activity startup based on the database contents. No need to reinvent the wheel here. Hope this helps.
Put your Collection of messages in the Bundle savedInstanceState at OnSaveInstanceState() and restore them in your onCreate() from that.
I have a tab host control that is loading tabs using fragments.
Each time a tab is switched it detaches the old fragment and attaches the new fragment.
I noticed that the OnCreateView method is called during this process, and that a lot of my state is getting lost since it recreates the view each time. However I noticed that some view state such as the value of edit text is being maintained across detach/attach.
I'm wondering how Android is automagically restoring state when the view is being completely destroyed and recreated as a new view. The value of the Bundle savedInstanceState is always null when I am just switching tabs. Bundle savedInstanceState only becomes populated when I do something like rotating the screen.
as far as I can tell this restoring of state is taking place just before the fragment onStart method is called.
When attaching and detaching fragments only the views are destroyed, the fragment instance remains the same.
The fragment manager restores the states of views that have ids, and the savedInstanceState is null.
In case of rotation, the fragments are probably recreated by you somewhere else (in activity's onCreate()?).
When a fragment is about to be removed from the window (or replaced) its onSaveInstanceState(Bundle) (or onRestoreInstanceState(Bundle)) method is called. This will propagate through the fragments hierarchy restoring its previous state.