8

I'm not quite understanding this fragment lifecycle business.

I have a pretty standard 3 page horizontal slider view Pager layout for a "view details" section of my app. I start my app on the middle page of the three. My FragmentActivity sets the page to page 1.

mPager.setCurrentItem(1); //default to center page, current data view fragment

I've been using the FragmentStatePagerAdapter because using the FragmentPagerAdapter crashed my app at times, when coming back from a suspended state for example, and this was the quickest way to work around that for now. Seems to work but I suspect the State aspect is what might be the cause of my problem here, maybe.

So at first I thought that I would have each fragment do the work of getting data from a rest service and then showing it in a list, but I'm not so sure any more.

I tried running a unique async task to fetch data in each of the fragments onCreateView events. Then after reading more on the fragment lifecycle I switched to onCreate, having noticed that the onCreateView was being called quite heavily, which in turn made for a greedy app that too often requested data over the wire.

Switching to onCreate hasn't changed anything. OnCreate is still geting called just as much as onCreateView for the 2 adjacent fragments.

The odd thing is that the fragment that I set to be the first one to display in Fragment Activity only gets the onCreate called the one time.

Something doesn't feel right here.

Right now I'm thinking that I should have the parent fragment activity declare and call all the async tasks to fetch the data that I need to display in the fragments. Set the results of the async calls in an object owned by the parent fragment activity and then have the fragments use the object contained by the parent to create the list view etc.

But what if the async tasks started by the parent activity don't finish before each fragments onCreateView is called and the object contained by the parent isn't ready yet.....

signed, confused and frustrated

topwik
  • 3,487
  • 8
  • 41
  • 65

2 Answers2

25

ViewPager is quite zealous in shutting down things it isn't currently using, and this is exactly what is happening here. The default behaviour is for ViewPager to "keep around" one page either side of the page being viewed, and destroy the rest. Hence in your 3-page view, page 3 gets destroyed when selecting page 1, then when page 2 is reselected page 3 is recreated. As you've noticed, page 2 only has onCreate(..) called once because it is always adjacent to, or is, the currently selected page.

To solve this, simply set ViewPager.setOffscreenPageLimit(2). Then the ViewPager will keep all your Fragments. Obviously this isn't a good idea for a large number of Fragments, but for your case it should be fine.

Alex Curran
  • 8,818
  • 6
  • 49
  • 55
  • oh ya, that sounds helpful to try. so, hey, does firing off async tasks from a fragment onCreate seem like a standard way of doing thing? right now i fire off three seperate async tasks once my fragment Activity loads, right or wrong.... – topwik Aug 07 '12 at 19:31
  • Yeah, the only issue I could potentially see with that is if a user rotates the device when the AsyncTask is running. I don't have much experience with them however. It might be worth checking out the AsyncTaskLoader class, I believe that the Loader classes automate a lot of stuff for you. – Alex Curran Aug 07 '12 at 19:48
  • 1
    Very good fix for guys who only use few tabs that don't consume a lot of memory (for my part I use 3). Moreover, the code will be a lot easier to maintains (easy start/stop cycle to manage !) – Tobliug Feb 23 '15 at 22:14
  • god bless..saved my life – DJphy Mar 05 '16 at 08:05
  • great answer, exactly what I was looking for – Ofek Agmon Sep 24 '16 at 12:32
2

@Espiandev's solution will work for your current case, but you're right that your state is the issue. You should use the setArgument and/or onSaveInstanceState methods to save your Fragment's state (which shouldn't be too hard, since e.g., a response from the server can usually be represented as a String), and then use getArgument and/or the Bundle passed in onCreate to restore it.

Alternatively, you could have your Activity do the server fetches, and then call setArgument for each of your fragments, and check the arguments inside your Fragment to determine if your data has arrived yet (and if not, potentially display a loading state of some kind).

If you care at all about screen orientation change, this related question will also be useful to you.

Community
  • 1
  • 1
Jon O
  • 6,532
  • 1
  • 46
  • 57
  • thanks, man. i appreciate the response. i wanted to follow up with, "what if i had many more fragments in this pager".... – topwik Aug 08 '12 at 15:21