I want to restart the fragment, i.e. recall the onCreate and onCreateView method of fragment when refresh button ia clicked. How to achieve it?
The answer probably lies in the getItemPosition() method of your ViewPager adapter. To quote from the Android Developers blog:
If you’re trying to replace Views in your ViewPager, it isn’t enough
just to change the data set behind the adapter and call
notifyDataSetChanged(). You also need to ensure that you’ve correctly
implemented getItemPosition(Object object) and return POSITION_NONE
for items that have changed and return POSITION_UNCHANGED or the
actual position for items that haven’t changed.
If you call notifyDataSetChanged() on your adapter, and your getItemPosition() is set to:
#Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
Then every fragment will be re-created from scratch.
Related
Our application has multiple fragments to show data specific to location. We have used FragmentStatePagerAdapter and ViewPager. User should be able to add new page and delete as well. While adding new page works fine, deleting the existing page shows issues. When I verified I had 3 pages. I deleted the 2nd one from left navigation menu button.When I try to slide to the 3rd page, it shows the view of delted page that is 2nd page. ANd it does not show the 3rd page.
I have Overriden getItem() where I return the new page. I have adjusted the ItemCount when I added/deleted the new page to Adapter. And I called startUpdate() before I add/delete, destroy() to delete any fragment object in a position, finishUpdate() after everything done. And finally notifyDataSetChanged().
Looks like nothing is missed but something. I still see the view of deleted fragment and next to it is blank page or something similar depending on which position's page I delete.
I see Removing fragments from FragmentStatePagerAdapter is something similar but could not help my case. Help me with any clue.
I could solve it. Though the answer by Wize here Replace Fragment inside a ViewPager does not solve my issue, I could find a hint from this. I had to override getItemPosition(Object object) which tells system that particulat 'object' is not-changed/no-more-exist.
I have the list of fragments (references) locally as well which I modify according to the list that FragmentStateAdapter maintians and here is my code for getItemPosition():
#Override
public int getItemPosition(Object object) {
if (object instanceof myFragment) {
if (!mFragments.contains(object)) {
return POSITION_NONE;
} else {
return mFragments.indexOf(object);
}
}
return super.getItemPosition(object);
}
Also, I only called notifyDataSetChanged() after I add/delete fragments. I removed startUpdate(), finishUpdate() all that.I do not knwo where exactly where they are used. But it worked without them.
I'm writing an application that uses the FragmentPagerAdapter. The fragments in the adapter need to be updated according to outside data - but that doesn't happen. I noticed that the fragment classes are only instantiated once, in the getItem function:
#Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(),
info.args);
}
Even if I delete the class and use a new one, nothing helps - this method is only called once, the first time that the tab is populated, and then never again. Anyone has an idea why?
Thanks!
getItem will be called whenever the adapter needs a fragment and the fragment does not exist.
If the fragment already exists in the FragmentManager then there is no need to instantiate it and getItem does not need to be called.
To update an existing fragment you would need to retrieve it from the FragmentManager or the adapter and manipulate it accordingly.
By default, the viewpager will create fragments for the visible page and the one next to it. I.e to start with, fragments in position 1 and 2. When you swipe to page 2, the fragment at position 3 will be created etc
To be more specific than the answer above (which is correct!), getItem is called by FragmentPagerAdapter's instantiateItem(ViewGroup container, int position) method. Just in case that helps :)
Simply use FragmentStatePagerAdapter instead of FragmentPagerAdapter
FragmentStatePagerAdapter destroys the instance of unneeded instance of fragments and instantiates again on-demand basis. On the other hand, FragmentPagerAdapter just detach the Fragment and reattach it. So fragments created in FragmentPagerAdapter never get destroyed. That's why I always prefer FragmentStatePagerAdapter.
I have a ViewPager with 10+ views. I wish to change the order of the pages occasionally i.e.
Page 1 | Page 2 | page 3
to
Page 3 | Page 1 | Page 2
For the tabs I am using ViewPagerIndicator, I am able to update the order of these by changing the order of my adapter and calling:
mViewPagerIndicator.notifyDataSetChanged();
However, what I cannot update is the content of the ViewPager, for example if I update the ViewPager adapter (to the new order I wish the pages to be in) and call:
mViewPager.getAdapter().notifyDataSetChanged()
This has no effect. The tab indicator bar is updated fine but the content of the page still shows the old order.
Is there a way to change the order of pages in a ViewPager adapter and get the ViewPager to reload all it's views?
My ViewPager adapter extends FragmentStatePagerAdapter and my overridden methods are as follows:
#Override
public Fragment getItem(int position) {
return MyCustomFragment.newInstance();
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
//super.destroyItem(container, position, object); // Commented out to ensure views are not destroyed
}
Thanks
It's tricky to do with FragmentStatePagerAdapter because you'll have to implement the logic yourself, but it's a lot easier with FragmentPagerAdapter which already provides the functionality for this purpose.
Calling .notifyDataSetChanged() invokes the getItemPosition(Object object)-method of your adapter. This is where you should provide ViewPager with the information of where to put the Fragment passed in the parameter object, by returning the page-number you want the Fragment to be positioned on.
For an example on how to do this, check out my answer here.
If performance isn't super important, it's really easy to force the FragmentStatePagerAdapter or FragmentPagerAdapter to redraw (invalidate) all of its views/fragments: just override getItemPosition and call notifyDataSetChanged() as you normally would.
#Override
public int getItemPosition(Object object) {
return POSITION_NONE; //In source code, POSITION_NONE = -2 FYI
}
For more info, check out my post: How to use orderByKey() in descending order instead of ascending #Askfirebase
i've a simple chat application with ViewPager for Active Chats, now, i use
#Override
public int getItemPosition(Object object)
{
return POSITION_NONE;
}
but this causes the all fragments to be recreated, and if there is too many messages it will lag, and also it closes keyboard whenever a message is received, so i attempted to override instantiateItem, but i couldn't get to anywhere, since i didn't know what to do with it, i wanted to update all listviews/fragments, not just the active one.
i also tried to use the onCreateView of fragments, get the listview, add an adapter to it, and add that adapter to a Array list, and whenever each messages comes, all adapters in this array list are updated, but this didn't work as expected, i had to move away from ViewPager then back to it again (Since the ViewPager is inside a tabHost) for messages to be displayed.
any help is appreciated, thanks.
Please use setTag() method in getItemPostion() for the views to update them rather then returning POSITION_NONE. The reason of using setTag() and the way how to do that is well explained in this post ViewPager PagerAdapter not updating the View
I am using a ViewPager plugged to a FragmentStatePagerAdapter. Each fragment contains a listview. In this listview I wish to display ads and make calls to a analytics server. I only want to make those calls when the user navigates to a fragment (so I cannot use the onCreateView or onActivityCreated events in the Fragment). Is there an event I can hook on to this end ?
Update
I realized that the way I am fetching my current fragment is flawe
#Override
public void onPageSelected(int page) {
this.currentPage = page;
tabsAdapter.getItem(page);
}
getItem(int position) in the pager is actually responsible for instanciating the fragments, so it would create a new unattached fragment (hence getActivity() returning null). I think I will us an approach where I keep a map of the fragments (<Position, Fragment>), i will remove the fragment from the map when destoryItem is called in the pagerAdapter.
You are right, best option is the second solution here:
http://tamsler.blogspot.nl/2011/11/android-viewpager-and-fragments-part-ii.html
so your thoughts are correct.
How about this:
http://developer.android.com/reference/android/support/v4/view/ViewPager.OnPageChangeListener.html
The onPageSelected(int) method sounds like it does what you want.