Restore fragment's previous state on rotation and position in backstack - android

I have an app with a single activity showing a fragment to the user. On a click on a button, the activity shows another fragment but keeping the previous one in the backstack. I have now two problems:
On rotation (particularly in the second fragment), the data entered in the EditTexts is cleared
I want the backstack to be also restored with the text previously entered in the second fragment.
The problem is that when I save data to bundle using OnSaveInstanceState(...), I successfully get it again from OnViewCreated(...) but when I use editText.setText(str), the text is not shown.
At the moment, I think this is because the fragment is then destroyed and recreated by the parent Activity.
How can I do to make it work properly?
Thanks.

Make your fragments retainable:
setRetainInstance(true);
See the following guideline on orientation change state android orientation changes `

Related

How to prevent fragment recreating when conditionally navigating to previous fragment

I have two fragments A and B.
A is a form which contains EditTexts and one value need to be selected from fragment B.
When using navigation component after selecting item from B and when conditionally navigating to A , EditTexts values are gone. The fragment is recreated. How to prevent this?
My intention is to get value from B to A without recreating A
Without seeing your code its difficult to give you a straight answer, but here are some general ideas
1) Add fragment A to the backstack this will persist it when you return from Fragment B
2) Find fragment A by its tag and if it exists do not create a new Fragment A when returning to it

Why is onDestroyView in a fragment called immediately after navigating with JetPack Navigation

Is it normal behaviour that onDestroyView() is called immediately when you navigate to a different fragment?
I call the following method to navigate:
findNavController().navigate(R.id.action_homefragment_to_detailsfragment)
Is there a way to avoid this? Or should everything be restored from a ViewModel? For example my last scroll position in a ScrollView..
Fragments on the back stack have their views destroyed, but the view state is saved and automatically restored when it comes to the top of the stack again (i.e., you hit the system back button).
Only views with an android:id have their state saved and restored, so make sure any important views have an id.

How to scroll to the top of a ListFragment

My situation: I have two ListFragments (call them A and B) managed by one Activity which keeps persistent references to both of these Fragments. When I click a button in Fragment A, I replace that with Fragment B. The problem starts when I do the following flow.
A -> B -> (scroll) -> (back button) -> B
In that case, when I go back to Fragment B the second time, the previous scroll position is maintained, which I don't want. Instead, I would like for Fragment B to start with its ListView at the top of its content.
Things I have tried which do nothing:
Calling setSelection(0) in onActivityCreated
Calling setSelectionAfterHeaderViews() in onActivityCreated
Calling smoothScrollToPosition(0) in onActivityCreated
Interestingly, all of these work if I post them on a Runnable. However, when I do that there is a weird flickering the second time I open Fragment B.
So, how do I get Fragment B to automatically scroll to the top each time it is attached to its parent Activity? I feel like there must be something blindingly obvious that I'm missing, but I'm really stumped right now.
You're calling the right methods, but you're calling them in the wrong place.
I assume you have code that switches between the fragments and you call it when an item is clicked in A. So whenever you do the switch set the scroll to the top, something along these lines:
protected void switchList() {
ListFragment a = (ListFragment) getFragmentManager().findFragmentByTag("a");
ListFragment b = (ListFragment) getFragmentManager().findFragmentByTag("b");
b.getListView().setSelectionAfterHeaderView();
getFragmentManager().beginTransaction().hide(a).show(b).addToBackStack(null).commit();
}
And one important note: never keep persistent references to fragments in your activities. Whenever you need a fragment get it from the FragmentManager. This is crucial since on configuration change (like a device rotation, or when your app is suspended and restored) the fragments are recreated, and the reference you kept leads to a 'dead' fragment. Not only is it a major leak, it will also prevent your code from functioning. any change you make to the saved fragment is not reflected on the screen because the screen holds the newly created fragment.

Access a detached fragment's view

I currently am using ActionBar's tab feature with multiple fragments each representing a tab.
On my last fragment there is a 'Submit' button that takes all the input that the user has done on all the fragments and submits it.
My problem is that since those other fragments have been detached (only the currently showing fragment is attached to the main view) their view gets destroyed so cannot be accessed using the fragment's findViewById().
How can I access the data the user inputted for these fragments? Interestingly, it does store all the inputted values in a bundle and restores them when the fragment is attached again, I'm thinking the answer lies somewhere there...
I fixed this by not calling .detach() but .hide().
Now in the activity findViewById() will actually be able to access the view of all its fragments since their UI is now not detached just not showing.

Proper way to save and restore fragment states on backstack?

I have looked around and found variations of this question, but all of the answers seem to be ugly hacks. Is there no easy and proper way to achieve this?
Say for instance I have Activity A, which has a FrameLayout that can hold one fragment at a time. Lets say that when the Activity is first started it loads Fragment A into the FrameLayout, which consists of a ListView. When an item is selected in Fragment A it starts up Fragment B. The way I am currently doing this is by simply hiding Fragment A and then adding Fragment B since this preserves Fragment A's state. I am of course also adding this fragment transaction to the backstack.
So now Fragment A exists on the backstack. Say now I go back to my Android home screen and go to another app. While I am doing this, the Android system decides to destroy my application because the system needs more memory. When I navigate back to my application, how am I supposed to properly restore the state of Fragment B, and Fragment A which is currently on the backstack.
I cannot use setRetainInstance() since it does not work for Fragments placed on the backstack.
Essentially what I am trying to do is restore the backstack to exactly how it was before my application was forcefully closed. So Fragment A should be on the backstack (but not showing), and Fragment B should be currently showing. If I hit the back button, it should properly pop Fragment A off the backstack.
Some notes
Since the application was forcefully closed, it's savedInstanceState != null. Same thing holds for the fragments.

Categories

Resources