I have a action bar with 3 navigation tabs: Fragment 1, Fragment 2 and Fragment 3. Now, I want to do a task whenever Fragment 3 selected, so I put my task code in onCreateView() method. However, I find that Fragment 3 does not do the task, it means the onCreateView() method is not called. (I check this by logging). The other strange things is:
- When I slide: F2-> F3: the task not work.
- When I slide: F1->F2->F3: the task work. (onCreateView() method called)
I don't know why F3's onCreateView() method called when I slide from F1 to F3?
Any ideas for this?
The remark from tyczj is correct but it does not give a solution to the problem.
In your F3, just override setUserVisibleHint(boolean) and when boolean is true, it means that F3 is now visible inside the ViewPager.
Note that you can rely on this method because you are using a ViewPager and it properly set the user visible hint when a fragment is shown.
When you are not using ViewPager, you can't rely on this method unless you are explicitly calling the method when you know that the fragment is visible.
EDIT : setUserVisibleHint() is not called by the ViewPager, but by the FragmentPagerAdapter.
Because a ViewPager loads the next view so that it is ready when you want to scroll to the next fragment. by default the viewpager loads the previous current and next fragment in the ViewPager so when you scroll from F1 to F2, F3 is going to be loaded in so that you have a smooth scroll when you go to F3
The previous answer tells you why what you are doing won't work. But to correct it you will want to create a AsyncTaskLoader and use the fragments LoaderManager to load and manage the task. See http://developer.android.com/guide/components/loaders.html
Related
I am using a ViewPager inside a TabLayout. The ViewPager has 3 pages where each page is a fragment.
When the activity containing the TabLayout starts, the fragment callback methods upto onResume() are called for fragment1, which is as expected and fragment1 is displayed on the screen.
However, logcat shows that the callback methods upto onResume are also called for fragment2, although fragment2 is currently not being displayed on the screen. This looks odd to me since onResume should only be called when a fragment is about to become visible.
When I select fragment2, onResume is called for fragment3, although fragment3 is not being displayed. So there seems to be a pattern to this behaviour.
What could be the cause for this?
Update: The ViewPager I am using is a subclass of FragmentPagerAdapter.
If is default behavior of ViewPager to call next Fragment when ViewPager is initilized.
You need to use setOffscreenPageLimit()
setOffscreenPageLimit() sets the number of pages that should be retained to either side of the current page
Default value is 1 so next Fragment to the left and to the right will stay in memory.
To prevent from calling next Fragment you need to set 0 value to OffscreenPageLimit
viewPager.setOffscreenPageLimit(0);
on the ViewPager object.
EDIT:
But i have checked by setting limit to 0.
setOffscreenPageLimit(0) will not work now. when you set limit to 0 you can see below warning in LogCat:
Requested offscreen page limit 0 too small; defaulting to 1
So i advise you to either call setOffscreenPageLimit(2) which will keep all your 3 Fragments in memory otherwise don't call setOffscreenPageLimit(int limit) on ViewPager.
Two things contribute to this behavior:
Fragments are not required to have a UI, in which case it is never "visible" on screen. Basically, if a Fragment is attached to an Activity, its lifecycle methods will be called as appropriate.
ViewPager loads items to either side of the item that is currently displayed. This is in order to have content to show as the user scrolls the page with his finger. By default the off screen page limit is 1, which means that when your first fragment is the current item, the second fragment is loaded off screen in preparation for scrolling.
You can always check which item is displayed by the ViewPager using getCurrentItem(). If you are having problems because the fragment are destroyed and recreated needlessly when they go beyond the off screen page limit, you can increase the page limit with setOffscreenPageLimit().
I'm using a ViewPager in my app. There are three fragments inside the PageAdapter that is set in the ViewPager. All works perfectly fine and I can switch between all three fragments. I have 3 buttons that allow me to switch between adapters 1 to 3. The problem is noticed when I click buttons 1 and 3 at the same time. Here's what happens:
Fragment 1 - Fragment 3
onAttach
onViewCreated
onResume
onPause
onAttach
onViewCreated
onResume
onPause
As you can see from above, the second fragment is never paused and therefore never resumed. Both fragments modify the same recycler view onResume so with the behaviour above I end up with the incorrect state of my recycler view.
Any thoughts on why this might be happening and how I can fix this?
A ViewPager loads (by default) the current page, the previous page and the next page, since you have only 3 pages the second fragment is always resumed.
the solution is to set up a OnPageChangeListener and modify the recycler view in onPageSelected instead in onResume
Scenario:
I using a ViewPager inside a Fragment. This ViewPager inflates 3 fragments (AFragment, BFragment, CFragment) pages using FragmentPagerAdapter.
I have printed logs inside
onCreateOptionsMenu
onPrepareOptionsMenu
of all 3 fragments.
Problem:
For AFragment when created onCreateOptionsMenu was called only once,
but when I swiped to BFragment onCreateOptionsMenu and
onPrepareOptionsMenu for BFragment were called twice. And similar
thing happened with CFragment.
Can anyone explain why this is happening and How I can avoid it?
Thanks.
Because android by defaults loads a next and previous fragment in background, in order to load fragments efficiently and to remove lag.
However you can customise the same by using setOffscreenPageLimit (int limit), Which is used to set the number of extra fragments you would like to load in background. By default its set to 1.
Read Android fragments strange load for more information
I am implementing Tab Layout with Swipeable Views in android. For implementation I had followed
AndroidHive
and
Tabs and swipe views.
But with both, I am facing the same problem. I am having 3 fragments but when my application run, onCreateView of 1st and 2nd Fragment called instead of only of 1st fragment's. When I swipe and go to 2nd fragment, onCreateView of 3rd Fragments get called.
So, whatever I code in 2nd fragment execute in the first fragment view. I researched and came to know that it happen to keep the next fragment into memory for smooth animation. But I am wondering, where I would code in the fragment so that it will execute only once or how to restrict Fragment getItem() method to be called only once. What can be the solution for this?
According to the Fragment's documentation you can implement the onCreate() link:
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.
This should fix your problem, because i guess you now only use the onCreateView which might be called more than once.
For more information you can check the Fragment's lifecycle or documentation
Good afternoon!
I have a method which crashed with NullPointerException if I call it immediately after launch , but If i slide through all fragments and then call the method, all works good.
As far as as consider, smth not initialize.
I need to fix this bug fast, so I want to slide through all fragments programatically between UI launch(in onCreateView or smth else). How can I do this ?
Here is RootFragment http://pastebin.com/VfmRbVpc
One of child fragments http://pastebin.com/XnftaqTH
I have a NullPointer in child fragment line 63
elview = (ExpandableListView) v.findViewById(R.id.expand_lv);
Thanks!
Fragments in a ViewPager are created on in a lazily manner so If you need access to a Fragment thats further down the line, you should attach a OnPageChangeListener to the ViewPager and execute the needed code when you reach the target index/position.