I have a 3-tab ViewPager with custom Fragments (EntryFragment and CalendarFragment; the third is not relevant to the question). Now when I click a date on CalendarFragment the EntryFragment should load up with data of the new date (I have coded it this way).
Now, what happens is something strange: The TextFields in EntryFragment get changed to the new data from the new date. But the Seekbars, Spinners, Switches, etc retain data from their previous date.
I am using the following methods to set the values of the various Views:
seekbar.setProgress(int);
spinner.setSelection(int, false);
switch.setChecked(boolean);
Also, I have attached onItemSelectedListerners for these components. These are getting called automatically after onCreateView() of EntryFragment.
Could anyone guide me why this is happening? Or how to prevent it?
I'm guessing it might be restoring previous state, ViewPagers have inbuilt mechanism to restore views that had been hidden. Your data is set to correct values and restored to previous state after that. To prevent that, try to add saveEnabled=false in xml layout of views you are having problem with.
Related
I am using a tabbed Activity. In one of the tabs I have two buttons and a Recyclerview. In the RecyclerView I have two spinners and an edittext.
The purpose of the first button is to add a new item in the RecyclerView and the second one is to save the chosen elements in the spinners and edittexts.
My problem is that when the screen is rotated, the Recyclerview is emptied. I tried using the OnSaveInstanceState() and the OnRestoreInstanceState of the LayoutManager of the Recyclerview to save the state but it still gets deleted.
I'd appreciate any help !
By default, activities and fragments have an onSaveInstanceState() method that the system uses to provide a Bundle to which you can write primitive data and parcelable objects.
This is okay as long as your data is simple. In your case, it isn't.
The framework may decide to destroy or re-create a UI controller in response to certain user actions or device events that are completely out of your control.
For example screen rotation (orientation change).
ViewModel comes to the rescue.
ViewModel is a class that’s part of the Android Architecture Components and it is lifecycle aware.
For more check this documentation.
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!
In my app there are two fragments and one activity. On all of them I used listview and fill the content from database. When rotate screen the position of content in activity don't change and start on correct way (as I googled and understand it is normal for activity because of "Bundle savedInstanceState"). My problem is with fragment part that both of the list on fragments are too long list and it could be annoying for end user when press back and came back to fragments start navigate to appropriate item. I googled and find some answer to my question but they don't work for me.
In this case, the states saving or restoring won't work anymore, because the listview was dynamically fill up by database or internet. when I facing this problem, I have a long size dataset for that listview, the rest datasets are coming because my data was show as pagination mode, user may scroll out far from first page, so when fragment destroying, all you can do just save the particular parameters to State Bundle, e.g. the page number, the selection index, the selection y-axis, finally restore the state by your own hands.
I am adding Views (not Activities) to a TabActivity on demand (meaning that the activity can have zero or more tabs after onCreate is done). Over the time more tabs get added, now I need to save them in a sane way so I can restore them later on. I tried to use saveHierarchyState etc on the individual views, but they are restored without data from the editTexts etc.
So given that I have a HashMap in the activity which maps from tabkeys to views, how would you save this data and restore it?
Okay, I got it :)
First I thought I needed to set the IDs of the Views as described here -- using this approach Android is able to restore the view states. But since my dynamic tabs all use views from the same layout their children all have the same IDs, so android will overwrite the data (The state is saved in a sparse array according to the view ID, so the IDs should be unique) and all views look the same. I fixed that by manually saving the state of my views and reapplying it via:
SparseArray<Parcelable> container = new SparseArray<Parcelable>();
saveHierarchyState(container);
b.putSparseParcelableArray("state", container);
restoreHierarchyState(b.getSparseParcelableArray("state"));
While this approach works I still have to find out if I can let Android do all the work by not setting IDs for the Views in the layout xml file (if that's allowed/possible).
I really,really need a serious help over here.
I am creating an android app which uses PagerAdapter to create Fragments in an activity. Different Fragment consists of different views according to need which are created during run time. In the last fragment, I have created a sort of "Submit button", which when clicked, is supposed to get user entered values from each views(like EditText) from all Fragments.
I am using following command to get the views(int the above mentioned button clicklistener):
EditText e = (EditText) (getActivity().findViewById(i));
But its not geting the view with that ID except of last two fragments.
So, I am assuming that, it is saving the state of only last two fragments in that activity.
So, How can I save the 'view states' of all the fragments in the activity??
And Isn't it so that, when a view is created in a Fragment, and is added in its layout , that view is also added in the main activity layout?? Am I understanding it in the wrong way??Please let me know.
To simplify it, my question is:
How can we save the contents, entered by users, in dynamically created EditText in Fragments, created using the ViewPager (So that it can be accessed later)??
When you add a fragment to a FragmentPagerAdapter (assuming you haven't written a custom pager) it is added to the FragmentManager. The Fragment manager is independent of the activity lifecycle so it retains the fragment state.
If you take a look here: http://code.google.com/p/ratebeerforandroid/source/browse/trunk/JakeWharton-ActionBarSherlock/library/src/android/support/v4/app/FragmentPagerAdapter.java?spec=svn42&r=42
You can get an idea of how it works. If you want to save the fragment state for another session you'll need to pull back each fragment (getItem) and either use the onSaveInstanceState or write your own custom function
Hope that helps