I have 3 fragments in the ViewPager.
PersonalFragment
CropFragment
NotesFragment
Every fragment has a RecyclerView and I was adding items using a dialog in it. However, when I go to the last fragment (i.e. NoteFragment), the first fragment's (i.e. PersonalFragment) RecyclerView gets empty (all items are removed). The same thing happens when I come back to the first fragment, the last fragment's RecyclerView resets (all items are removed).
It is difficult to understand without seeing some of your code which is related. I think you might have implemented the onResume function incorrectly. Each time you go to the third fragment in your ViewPager, the first Fragment needs to be reinitialized and you need to take care of this in your onResume function.
However, another workaround for your problem is setting the off-screen page limit of the ViewPager like the following.
viewPager.setOffscreenPageLimit(2);
Hope that helps.
Related
I am having this problem with nested viewpagers.
I have two levels of viewpager. Lets call it levelOneViewPager inside which I have one more viewpager, let's call this levelTwoViewPager.
The Activity loads the data for levelOneViewPager and sets the adapter.
The levelOneViewPager loads data for levelTwoViewPager in onViewCreated and sets the adapter.
Everything works fine when the levelOneViewPager loads data for first time.
Now here is the problem.
First page of levelOneViewPager is loaded, I move to 4th page and come back to first page and the app crashes.
Reason, now first page of levelOneViewPager is recreated and is loading the data, even before it sets adapter, the fragments of levelTwoViewPager are created and is accessing some data in the parent fragment which is not available yet.
How is this happening? I haven't set the adapter to levelTwoViewPager yet but fragments are created for it.
(I tried using both FragmentPagerAdapter and FragmentStatePagerAdapter, it's the same behaviour)
add offscreenpage limit to parent viewpager this should fix the issue
I think the easiest way to show the problem is the gif below. When i'm on the home fragment, and switch to Recent, Recent is a fragment with ViewPager and TabLayout, the item that's supposed to be in the recyclerView shows up normally, but when i go back to Home Fragment, and go back to Recent, the Item is not there anymore. I believe that it has something to do with the fact that when I go back to the Recent Fragment, even though the Recent Fragment's onCreate() is being called, the 'All' Fragment, which is the first in the ViewPager is not calling it's onCreate().
It's calling the onResume() however, and i check the RecyclerView's list size in there, and it still has the item in it, it just not showing up.
How can i fix that?
Is there a way to force the FragmentPagerAdapter to call onCreate() on it's fragment's, like the 'All' Fragment when going back?
Found the solution, didn't know where to even look for the problem so i didn't post the code in question to not make it too long.
When using a ViewPager inside a Fragment, don't use getActivity().getSupportFragmentManager() when creating FragmentPagerAdapter, use getChildFragmentManager() instead.
So when it comes to code, use this:
MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(getActivity(), getChildFragmentManager());
Instead of :
MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(getActivity(), getActivity().getSupportFragmentManager());
I am trying to implement swipe views with 2 tabs. For that, I am using view pager with 2 fragments. Now, the problem is that as soon as the main activity is opened (that contains those two tabs), onCreateView function is called for both the fragments. Please help me as how can I avoid calling of onCreateView of second fragment when one is in use.
Thanks,
Arpit
ViewPager retains the fragment to the left and to the right of the current view by default. This is to reduce a choppy user experience - that way you can begin swiping left or right and immediately see what is there without delay.
It is possible to disable (or increase the number of fragments to be retained) with setOffscreenPageLimit(0), but seriously consider if this is the right approach.
I have implemented an activity that displays fragments in a viewpager. The activity initially displays 5 fragments of a given type (type A). Each type A fragment contains a list of information. When a button is pressed, the fragments are replaced with another tpye of fragments, type B (i.e., fragments that use a different layout and display different information are loaded).
I have implemented this with a ViewPager and a custom FragmentStatePagerAdapter. The custom FragmentStatePagerAdapter overrides the getCount, instantiateItem, getItem, getItemPosition, etc. functions and all works fine. When I press the button the views switch from fragment type A to fragment type B. In order to do this I am using a replace fragment transaction and I also call notifyDataSetChanged on the adapter. The switch from type A to type B fragments is accomplished by checking which type of fragment I need to create in the adapter's getItem function. The problem is that the switching process (i.e., changing from fragment type A to fragment type B and vice versa) takes some time (around 2 seconds) - this delay is quite noticeable and annoying.
This occurs because the adapter's getItemPosition function returns POSITION_NONE. When POSITION_NONE is returned, the viewPager recreates the fragment. Furthermore, when the replace transaction is executed, all items of the adapter are removed and all new ones are recreated. The same happens when I switch back to fragments type A.
Does anyone know if there is a better or faster way to do this? Using a FragmentPagerAdapter should not be a good solution since the number of fragments in the viewPager could grow.
I have commented out the updating of the fragments and the problem is gone so the problem is the time it takes to update the fragments. Is there a way to update the fragments asynchronously? That should take care of the problem.
The ViewPager instatiates by default a minimun count of Fragments. In general the left and right one of the current Fragment. So you don't need to care about the total number of Fragments.
You can control the total number with the ViewPager.setOffScreenPageLimit() method.
Also a AsyncTask seems to be a good idea to manage the intensiv work of your Fragments.
Scenario:
I have a fragment which has a ViewPager which contains 5 instances(different) of a single Fragment with different values, each having a listivew that contains some sort of items.
Problem:
The flow goes smooth when I click an item of listView(say on page1) but the moment I come back from there on pressing back (overridden OnBackPressed in the main_activity (will discuss later)), the viewPager fails to load the subFragments.
But when I switch to the 2nd or 3rd page, it gets displayed, and on going back to 1st page, it now gets displayed.
OnBackPressed():
I am maintaining a manual stack here. When I click on an item of ListView, the current Fragment Instance (of the parent Fragment ofcourse) goes into stack. And when user comes back , that instance gets popped off the stack and I replaces it on the activities FrameLayout container.
References:
Fragments not getting recreated by FragmentStatePagerAdapter after coming back to the main Fragment instance
Guys, I am really pissed off here, please help me out.
Frankly, I haven't worked much with fragments.
But it seems like the page is being thrown off the memory every time you switch to other pages. I am not sure but if there is a way for android to manage this and keep the page in its memory persistently, it might solve the problem
Finally I am able to get a workaround for this issue, which included two things:
while replacing the fragment make a call to
ft.replace(R.id.content_frame, frag).addToBackStack(null);
while initiating the ViewPager, the fragment manager to be used is :
mAdapter = new myAdapter(getChildFragmentManager());
Actually the problem is that, android fails to recognise and load the older instance of the fragment unless you explicitly add that instance to the backstack. So after adding it to BackStack, there is practically no need to maintain your own manual Stack, but you still can do that.