3

How exactly v4.app.Fragment works? I have viewPager with 7 Fragments. I was sure that when moving between fragments, depending on the situation each fragment can be automatically destroyed and created. However it seems not to be true.

I decided to play a bit with debugging and set some flag for my Fragment class object, something like

class MyClass extends Fragment {
public boolean myFlag=false;

When I set ex. true somewhere in the code which is run only once (ex. true is set after button click), it seems that this value is true until the app ends. Thus it suggest the object is kept all the time in memory.

However when user moves between Fragments onCreateView and onViewStateRestored methods seems to be called.

And now I feel quite confused. If Fragments are not destroyed, why those methods are executed by Android?

Do I have the guarantee that my Fragment object will be kept always with all fields (when user only moves beteween Fragments and doesn't leave the app)?

If not how should I save and restore its state? public void onSaveInstanceState(Bundle savedInstanceState) method seems to be only run when user left the app, not when user moves between Fragments.

Have you seen any good tutorial concerning ViewPager and Fragments?

user2707175
  • 1,133
  • 2
  • 17
  • 44

2 Answers2

3

And now I feel quite confused. If Fragments are not destroyed, why those methods are executed by Android?

If you look at this diagram, Fragments do not need to be destroyed to call onCreateView(). enter image description here

Do I have the guarantee that my Fragment object will be kept always with all fields (when user only moves beteween Fragments and doesn't leave the app)?

This depends on what you are doing. If your case is dealing with ViewPager it really boils down to what PagerAdapter you use and your ViewPager configuration.

If not how should I save and restore its state? public void onSaveInstanceState(Bundle savedInstanceState) method seems to be only run when user left the app, not when user moves between Fragments.

It depends under what conditions you are wanting to restore state. For example, for orientation changes you can call setRetainInstance(true) on the Fragment and the Fragment's state will be preserved when there is a configuration change given your Fragment is not on the backstack.

Have you seen any good tutorial concerning ViewPager and Fragments?

The Android Guide has a good tutorial.

Emmanuel
  • 13,083
  • 4
  • 39
  • 53
  • Thanks a lot. I use FragmentPagerAdapter. In this case, do I understand well, all fragments should be kept alive? – user2707175 Jan 25 '14 at 20:50
  • Returning to saving state, if I use adapter which creates and destroys fragments dynamically, how to save and restore state then? – user2707175 Jan 25 '14 at 20:51
  • And this Android Guide even if it gives some additional info, doesn't seems to answer on all my doubts unfortunately. :( – user2707175 Jan 25 '14 at 20:56
  • You might want to read [this](http://stackoverflow.com/questions/18747975/difference-between-fragmentpageradapter-and-fragmentstatepageradapter/18748107#18748107) answer I gave regarding `FragmentPagerAdapter` vs `FragmentStatePagerAdapter`. – Emmanuel Jan 25 '14 at 20:56
  • If you are restoring state you are probably using `FragmentStatePagerAdapter`. [This](http://stackoverflow.com/questions/16416170/save-state-and-restore-state-in-fragmentstatepageradapter) answer seems to give a good explanation. – Emmanuel Jan 25 '14 at 20:58
  • thanks a lot for all help. It seems that when using FragmentPageAdapter all fragments will be kept in memory and the only situation when the state will have to be saved will be the moment when user exits and returns to the app (assuming it's kept in the background). In the links with asnwers I don't understand one part "The first Adapter might destroy View hierarchy and re load it when needed, the second Adapter only saves the state of the Fragment and completely destroys it, if the user then comes back to that page, the state is retrieved." Could you explain it a bit more please? – user2707175 Jan 25 '14 at 21:06
  • `FragmentPagerAdapter` will retain the entire `Fragment` (it might get rid of the `View` hierarchy if the `Fragment` is not visible). `FragmentStatePagerAdapter` will only retain the state of the `Fragment`, meaning that you will have to re initialize variables if they contained values before. – Emmanuel Jan 25 '14 at 21:08
  • For FragmentPageAdapter I understand. But why FragmentStatePagerAdapter will keep the state of Fragment if it sometimes destroys it assuming I understand it well? – user2707175 Jan 25 '14 at 21:13
  • And one thing more - how to check if Fragment has the View hierarchy attached or is that destroyed? – user2707175 Jan 25 '14 at 21:15
  • `FragmentStatePagerAdapter` will destroy the `Fragment`. It will save the sate so when the user swipes back to that `Fragment` you can create the illusion that it was always there. It is your responsibility to re initialize `Fragment` to the state it was in. You do not need to care about restoring the `View` hierarchy when using `FragmentPagerAdapter`, the system will build it back for you if needed. – Emmanuel Jan 25 '14 at 21:17
  • Ok great. But I want to reset listView by executing listView.clearChoices() however I'm doing it from another Fragment. If the one with listView is not visible then (or more previsely View hierarchy doesn't exist) then clearChoices seems not to work. Thus I have to check if my Fragment has the Viev hierarchy attached or no? How to do that please? – user2707175 Jan 25 '14 at 21:21
  • You should not modify a `Fragment` from another `Fragment`. You should create an interface that the `Activity` that contains both `Fragments` should implement, so it is the `Activity` that actually manages the changes. – Emmanuel Jan 25 '14 at 21:25
  • Yeah, it's exactly done as you said. It was some kind of simplification from my side. One Fragment calls Activity and Activity calls all fragments having implemented the given interface. But in the consequence the listView should be reset then and it will not be if the fragment containing this listview doesn't have the attached view hierarchy. In such a case my app should store the info and reset the listview when the view hierarchy will be recreated. But I don't know how to check if view hierarchy exist or no.... – user2707175 Jan 25 '14 at 21:30
  • Check to see if getting the root's `ViewGroup` returns null. – Emmanuel Jan 25 '14 at 21:32
  • If I understand well if (getView()!=null) seems to solve this issue. Emmanuel thanks really a lot for all help. – user2707175 Jan 25 '14 at 21:40
1

You can re-initialize all the values of a specific fragment in it's onCreate(...) method. So that when ever it is navigated to, it will have the default values that you setup in your onCreate(...) method.

Here are some useful links related to the Implementation of Fragments in a ViewPager:
1. http://thepseudocoder.wordpress.com/2011/10/13/android-tabs-viewpager-swipe-able-tabs-ftw/
2. http://androidtrainningcenter.blogspot.co.il/2012/10/viewpager-example-in-android.html
3. http://manishkpr.webheavens.com/android-viewpager-example/
4. http://thepseudocoder.wordpress.com/2011/10/05/android-page-swiping-using-viewpager/

I hope this helps.

Salman Khakwani
  • 6,684
  • 7
  • 33
  • 58
  • Thanks for all those links. They give some "light". However they doesn't explain when fragments are created and destroyed automatically and how to store fragments state correctly (in one example they use onSaveInstanceState(Bundle outState) but I'm not sure if it's enough as basing on my experience this method is called only when leaving the app, not when moving between fragments). – user2707175 Jan 25 '14 at 21:02