Android, fragment state after FragmentTransaction.add - android

I have two fragments,
fragmentA in foreground
now I show fragmentB with FragmentTransaction.add(id, Fagment), (not .replace) so the fragmentA is still alive, with fragmentB on top of it,
now I use back button, here the fragmentB is destroyed, leaving fragmentA visible,
at this moment, how would I know that fragmentA has returned to the "foreground", ie onResume,
note that onResume is not called, due to FragmentTransaction.add(id, Fagment), in other words, fragmentA doesn't go onPause when fragmentB is shown
thank you very much for your help

If you want to know when fragment A becomes visible again, you can first hide it in the fragment transaction that creates fragment B:
fragmentTransaction.add(id, fragmentB).hide(fragmentA).addToBackStack(null);
Then in Fragment A, override onHiddenChanged:
#Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
// Handle visibility changed. Note this method is called only when the state is changed.
}
When the back button is pressed, the fragment transaction will be reversed and the fragment's state will be changed to visible. One thing you have to watch out for: I've noticed that the hidden state isn't preserved between activity rotation so you'd have to perform your own bookkeeping in onSaveInstanceState. I do something similar to what you're asking since in my case the fragment views are expensive to recreate.
Before doing this though, you might want to consider handling your fragments another way, like with .replace() instead of .add(). If your fragment is completely hidden by the new fragment, then maybe you don't need to keep it around, and you can let the fragment manager bring it back once the user hits the back button. That way, you can just use the normal lifecycle functions like onPause and onResume.

Related

Save Fragment Data onreplace and fill in after popbackstack

I have FragmentX in a ViewPager. FragmentX has EditText's in it and a Button. The user presses the Button and FragmentY replaces FragmentX. The user then presses back and FragmentX has lost all of its input from the user.
How do you either:
a) Save the data in FragmentX before FragmentY appears then FragmentY is replaced by FragmentX retrieve the data and fill in the EditText's in FragmentX
(please don't reply with OnSaveInstanceState, as this does not work unless the Fragment is destroyed, which in this case it is not)
b) somehow keep the data in FragmentX so it is there when we go back to FragmentX from FragmentY..
Any suggestions?
Using addToBackStack() might help in your case.
If you return to a fragment from the back stack it does not re-create the fragment but re-uses the same instance and starts with onCreateView() in the fragment lifecycle, see Fragment lifecycle.
So if you want to store state you should use instance variables and not rely on onSaveInstanceState().
Check this out: Maintaining fragment states
I am now saving the data in FragmentX to SharedPreferences and overriding onBackPressed in the Activity, and have created a function in the Activity called popFromBackstack where the popBackStack() occurs.
In the functions in my Activity where i replace my Fragments i am now saving the data in FragmentX into SharedPrefs before the replace. I am also checking after the replace if the new Fragment is FragmentX and, if it is, i am filling the data into FragmentX from SharedPrefs.
I am also saving the data from FragmentX in onBackPressed in my Activity (if the current fragment is FragmentX), incase the user presses the back button.
I have also created a public static activity called popBackStack() in my Activity which i call from Fragments to pop the backstack. I am also saving the data from FragmentX here (if the current fragment being popped is FragmentX). Once the Fragment being popped is popped i am checking if the new Fragment is FragmentX, and filling in the data if it is...
Long winded approach but i couldn't figure out any other reliable way. This is working perfectly.
I suggest following guidelines that Google provides and implement an interface declared in your Fragment and save the Bundle or whatever object you want in the activity. Then, in your newInstace() static factory method pass that Bundle and recreate data as usual. Since you are using a ViewPager and it will always render the second fragment before the button is pushed (I assume your second fragment is in another tab) you still need to manage it via an interface. When the back button is pressed, the data will still be there, unless it is destroyed, and you still need to implement onSaveInstaceState() for that matter. You can also use setRetainInstance(boolean retain). See here for more details

Force onDestroyView on a fragment's view

I'm writing an app that loads user profiles and user's ratings for different places. The app uses fragments pervasively, and it's relatively easy to jump from a profile to a rated place.
As a user clicks a profile and gets to a rated place, they can click another profile on a rated place and go on and on.
The problem I'm having is memory related, when I'm looking at a ranked place and I click a profile, I switch from one Activity to the next. In both of these activities, after setContentView I load a fragment dynamically into layout space.
Now, as I shuttle between these activities, onSaveInstance state is almost always called, however since the Fragment displaying whatever was in the foreground before the activity switch, onDestroyView is not called.
What I would like is when onSaveInstanceState is called in these dynamic fragments, it to force onDestroyView to be called as well.
The only time onDestroyView seems to be called is when I add a Fragment to the back stack. When another activity comes to the foreground and this fragment is stopped, I'd like on DestroyView to be called as well.
The current workaround I want to implement is have an empty fragment with no view, and every time I call startActivity(Intent i), load this dummy fragment to destroy views and start the next activity. Then, when I come back, pop it off the back stack and restore the actual last fragment.
This however seems excessive. So, for a stopped fragment in a stopped activity with a new activity in front of it, how do I force it to destroy it's View?
First, you should not force or satisfy onDestroyView to fix your code, that's the job of the FragmentManager and the Android lifecyle # Pausing and Resuming an Activity. If you want to work with your existing code, use the other override methods onPause() or onStop().
Without posted code, I assume you're using the replace() method to display one fragment over another. This more or less forces you to manage the fragments yourself, some developers actually succeed in doing so with some struggle (look at other SO questions).
So my suggestion for you is either:
Maintain your own states, and show the proper fragments based on the state.
Use the BackStack and let the Fragment management handle the stack/states.

Understanding the fragment and activity lifecycle and backwards navigation

I'm trying to understand some odd behavior. I have an ActivityA that calls a method in onCreate() to add FragmentA to R.id.fragment_container. Inside FragmentA I have a button that attaches FragmentB by using ActivityA's fragment manager (getActivity().getSupportFragmentManager()) and replacing the R.id.fragment_container and I also add it to the backstack. I also have another button that starts a new ActivityB.
When I navigate back from ActivityB I get: ActivityA onResume(), FragmentA onResume(). But when I navigate back from FragmentB I get: FragmentB onCreateView(), FragmentB onActivityCreated() then the 2 onResume().
So my questions is...why is the view state saved when a new activity is launched and not when the fragment is replaced and reattached. It looks much better to just restore that state rather than recreate the views and fetch that data again. This seems like opposite behavior from what I would expect so I'm clearly missing some fragment state saving/restoration step or something. It seems like the activity is just pausing FragmentA (and ActivityA) when ActivityB is launched and restoring it on back pressed but when FragmentB is attached FragmentA gets completely destroyed. I'm sure there's a way to prevent this I just can't seem to figure it out. Thoughts?
Just below your question are four tags android,android-fragments,android-lifecycle& android-navigation .Put your cursor over it for a while a black box will pop up . click on info tab and you will get best links to study that topics along with links to books .
Hope this will help you

Fragment onStart and onCreateActivity called after back button press

Scenario:
I have a single Activity in which I have multiple fragments and I'm replacing one fragment with another using fragment transaction and add them to BackStack. I am doing JSON parsing and network related task on some fragments.
Problem:
My problem is that after replacing the fragment when I press back button to nevigate to last fragment the onStart and onActivityCreated methods called again. My code in these events execute each time I navigate to that fragment by using back button
But
Any value in EditText remain same in even after replacing the fragment and coming back to it using back button.
Why onStart and onActivityCreated executed each time?
Is there any method where I can put my code which do not execute after coming back to fragment?
UPDATE
Basically I want to set a button text once fragment is created. User can change that text. but when I return back to that fragment the users value change with the default text which I set on fragment creation time.
Thanks
You can put your code to run only one time at fragment creation in onCreate() of fragment..
onCreate()
The system calls this when creating the fragment. Within your implementation, you should initialize essential components of the fragment that you want to retain when the fragment is paused or stopped, then resumed.
See the life cycle of fragment.
You can also get more details here

Fragment onResume not called

I am having 4 (let's say 1,2,3 & 4) fragments. And at a time any one of them will be visible to User. In 2nd fragment I want to do something when user is coming on it.
Now when User navigated to 3rd fragment & hits the back button, I want to run a some code. My problem is onResume is not getting called when user hits the back button & come to 2nd fragment.
I recently bumped into the same problem, I know that its too late, but just in case some one else is looking for this, here's my answer:
Thanks #fasteque for narrowing down my search.
The fragments onResume() or onPause() will be called only when the Activities onResume() or onPause() is called. They are tightly coupled to the Activity.
But if you still want listen to the changes in your activity like which fragment is on top, and trigger events accordingly, you might wanna have a look at FragmentManager.OnBackStackChangedListener
Hope this helps :)
I've had the same problem. If you want to switch from 3rd fragment to 2nd fragment (with the back button or another way) you can call 2nd fragment in the onPause of 3rd fragment.
#Override
public void onPause() {
super.onPause();
Fragment2 fragment2= (Fragment2) getActivity().getSupportFragmentManager().findFragmentById(R.id.fragment2);
if (fragment2!= null) {
//you can call any function from fragment2
fragment2.SomeFunctions();
}
}

Categories

Resources