Deleting page from FragmentStatePagerAdapter causes issues - android

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.

Related

xamarin android viewpager fragments not getting refreshed

I'm using this sample to create a simple app, it's made by Joshep Raco (JoeRock11)
https://github.com/JoeRock11/Xamarin_DesignLibrary
I have a problem, I was working with this sample to create a tabbed app, and I found an strange behavior, when the app is starting only the fragment1 and fragment2 loads , but not the fragment3 (when I say load I mean their oncreate and oncreateview method gets triggered ).
To load the fragment3 I have to explicity click it, I thought all the fragments would get load but is not the case, don't know why, I would like to know why this happens.
Also, and this is my main problem and I dont know how to fix it, every time I click a fragment tab, I want this fragment to reaload, now seems like it just shows the instantiated fragment on memory, because it doens't triger any method of the fragment, I need to load it again, because I need to refresh its data, now it only reloads randomly. can you or anyone help me solve this please?
Thanks a lot in advance.
pd: sorry for my english, it's not my mother language.
I believe this is controlled by the Off Screen Page Limit on the ViewPager control. This value defaults to 1, which basically means, the number of the pages the ViewPager should load at a time is 2, the page that is currently displayed, and the one off screen.
This value can be easily adjusted using the OffscreenPageLimit property on the ViewPager.
http://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit(int)
If you want all Fragments to reload data once they are slid on to the screen, you can override UserVisibleHint on each Fragmentand then check to see if the Fragment is visible and execute some code to reload data for that fragment:
public override bool UserVisibleHint {
get {
return base.UserVisibleHint;
}
set {
base.UserVisibleHint = value;
if (value) {
//Fragment is visible, reload data
}
}
}
http://developer.android.com/reference/android/support/v4/app/Fragment.html#setUserVisibleHint(boolean)
Another approach to updating the ViewPager fragments is outlined here: Update ViewPager dynamically?

ViewPager and Custom Adapter

I have set up a ViewPager with a custom Adapter. That Adapter caches Fragments it shows. Code looks like this:
#Override
public Fragment getItem(int position) {
Fragment f = getCachedFragment(position);
if (f == null) {
//create and add fragment to cachedFragments
}
System.out.println("getItem: Fragment named:" + mTabs.get(position).clss.getSimpleName() + " with Hash " + f.hashCode());
return f;
}
Everything works fine. Except that the initial Fragments shown by the Fragment don't appear to be created using the getItem() method.
I have verified that 2 different kinds of fragments are being initiated, one with the getItem() method, and another one in a miraculous way I'm not able to explain. The Problem is that properly created one isn't the fragment which is being shown, so trying to access it and manipulate a view on it will fail, since onCreateView() has never been called.
As you can see every fragment created or retrieved is logged in chat with the corresponding hashCode. In addition to that I have added another system.out which tells me about new instances of a fragment.
Now, when I am on index 0 of the ViewPager, the fragment for index 1 is loaded as well, but not using getItem(). My Question is, how is that Fragment for index 1 initiated? I checked ViewPagerAdapter documentation but it doesnt provide any kind of solution since it just says it uses getItem() to get the corresponding Item.
Any pointer in the right direction would be greatly appreciated.

My fragments in viewpager tab dont refresh

i got viewpager with 4 tabs .. in each tab there is a fragment.
my first tab is a fragment with a form (for example Users)
after i click save, the data is inserted in the database.
my second tab is another fragment with form but it uses data from the first tab (i am getting it from the database) to populate a spinner.
now after i successfully inserted data from my first tab, in my second tab the spinner is empty. since my db query is implemented in onCreateView() in the second fragment, its called only once when the application is started, so changing between tab 1 i tab2 doesn't starts onCreateView() or even onResume().
The interesting thing for me is that if i go to tab4 and then return to tab2, my data is in my spinner properly, so somehow swiping two tabs away from my current tab refreshing my fragment.
my question is how can i achieve proper refresh to my fragment when onCreateView() is called only once ?
Edit
i tried to put that method psykhi suggested like that:
this.mViewPager.setOffscreenPageLimit(0);
this.mViewPager.setAdapter(this.mPagerAdapter);
this.mViewPager.setOnPageChangeListener(this);
but it's not working for me. Am i missing something ?
The best way that I have discovered to simulate a "setOffscreenPageLimit(0)" behavior is by using an OnPageChangeListener in conjunction with overriding the getItemPosition method in your adapter. Something like this:
In your custom pager adapter:
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
Then in your Activity containing the ViewPager:
final MyPagerAdapter adapter = new MyPagerAdapter();
pager.setAdapter(adapter);
pager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
... anything you may need to do to handle pager state ...
adapter.notifyDataSetChanged(); //this line will force all pages to be loaded fresh when changing between fragments
}
}
This should have the same effect as setting the OffscreenPageLimit to 0. However, this functionality is sort of against what the ViewPager is designed to provide. If you are trying to implement a ViewPager in this way, it may be worth reevaluating your layout to be sure that a ViewPager is really what you want to use.
UPDATE: There is a better way, Please have a look here: Update ViewPager dynamically?
Removing content of this answer because it was a really bad way to access Fragments inside ViewPager, please see the above link for better approach.
It's because you can specify the number of fragment your viewpager will "keep in RAM" (setOffScreenPageLimit () :I think the default is 1). So your second fragment is not reloaded. And when you go to a tab 3 or 4, then your 2 firsts fragments are deleted, then recreated when you come back.
To refresh your fragment, there is many way to do it: you could implement a listener interface of your own in it to tell it when to refresh, or simply call a method that you would implement to update your contents.
first override in the fragment method
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
actionView();//call the method to be refreshed
}
else{
//no
}
}
In my experience, ViewPagers keep:
Your current tab
& 1 tab either side in memory
So when you switch between 1 and 2, nothing is happening under the hood - it's like they are simply being hidden / shown.
But when you navigate to tab 4, tabs 1 & 2 are destroyed (onDestroy() called), so when you navigate back to either of them, they are being re-created fresh (onCreate() called).
As psykhi suggests, you could setOffScreenPageLimit() to 0, so that each fragment is created every time you navigate to it.
If you were interested in keeping the other pages in memory for performance purposes, as they were designed with this is mind, you could use a messaging/event publishing system to send a message from tab 1 to tab 2 telling it to update when you submit the form on tab 1.
Ok may be a late reply,might help others in future, so recently I faced same issue while fetching data from db into tabs it used to display only once I click on 3rd tab.. I tried above mentioned solution but nothing really worked.. fianlly i came across Otto
This library allows you to communicate within your app..
Just use this library to yourAdapter.notifyDataSetChanged() wherever you fetching your data from db..
This video helped me alot https://www.youtube.com/watch?v=lVqBmGK3VuA

Switch current fragment on item click

I am trying to write a file manager for android as an university project. My idea is to use fragments in it to create a tabbed vew for it with a viewpager. Practically, the first view you get when you load the app is a path selection fragment, where you have sdcard, music, etc. That fragment contains a listview of said folders. When I click on an item, i want another fragment to be added to the pager, and that works fine. But I also want the current fragment to be replaced with a grid view of the "clicked" folder. That doesn't work. I use an arraylist of File[] to store files in each folder i selected. I also added methods inside the fragment adapter to add and replace fragments in my fragment arraylist. Tried with transaction and with my list, the list is correctly updated but the view is not. The following code is the method inside my fragment adapter to replace a fragment. It is called inside an onItemclicklistenr set to my listview:
public void replaceFragment(SherlockFragment newFragment, int pos) {
SherlockFragment old=fragments.get(pos);
fragments.set(pos, newFragment);
notifyDataSetChanged();
}
I read several answers about this issue, tried almost everything, nothing seems to work. Any help would be apreciated.
I found an horrible solution. After updating the fragment list (without fragmenttransaction) I re-set the adapter for the view pager and restore the current Item. This way I force the fragments layouts to be built. Not beautiful, but whatever. This is the interface that gets called onclick:
#Override
public void onPathSelected(int position) {
// TODO Auto-generated method stub
Log.d("positioninsideintfc", Integer.toString(position));
firstrun.add(true);
int current=mPager.getCurrentItem();
root=(File) filepaths.get(position);
fragmentfilelists.add(root.listFiles());
initpath=MainActivity.root.getAbsolutePath();
Gridfragment newfrag=Gridfragment.newInstance(current);
mAdapter.addFragment(Selectpathfragment.newInstance(current+1));
mAdapter.replaceFragment(newfrag, current);
mPager.setAdapter(mAdapter);
mPager.setCurrentItem(current);
}
You should learn your Activity to speak the language your frament use. In general your Activity should implement Interface which then your fragments will use for communication. So in your case, when user tap the list item, the fragment with listview shall tell its parent Actity (using said interface) something like "user clicked on this". And your parent activity should do the rest, replacing/adding fragments. Your fragment, like in OOP, shall be not aware of existence of other fragments.

Updating ListView inside Fragment (ViewPager)

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

Categories

Resources