FragmentStatePagerAdapter onPageSelected event

I have a FragmentStatePagerAdapter with 6 fragments inside.

Each fragment connects to the server and downloads data.

Right now, the connection to the server is performed in Fragment.onStart (), which means that at any moment I have 3 http requests (the selected fragment and one on each side).

At that time, I want to have only one connection, so I rely on using

viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(final int position) { CustomFragment fragment = (CustomFragment) myFragmentStatePagerAdapter.getItem(position); fragment.onSelected();//do stuff in here } }); 

The fact is that getItem() returns a new fragment instance that has not yet been added to the manager (and, therefore, a view that has not yet been created, etc.).

Also, I tried setUserVisibleHint(boolean isVisibleToUser) , but is not a visible call, only on isVisibleToUser = false

So how to achieve the onPageSelected () event for a fragment?

Thank you in advance

+6
source share
4 answers

The best solution for you would be to override setUserVisibleHint() . Make sure you stretch the FragmentPagerAdapter . From its source code, you can see that it calls setUserVisibleHint(true) for visible snippets. I use it all the time and it works well.

 // adapter public static class PlayerAdapter extends FragmentStatePagerAdapter { public PlayerAdapter(FragmentManager fm) { super(fm); } @Override public int getCount() { return 6; } @Override public Fragment getItem(int position) { return new SimpleFragment(); } } // fragment public class SimpleFragment extends Fragment { private static final String TAG = BookControlsFragment.class.getSimpleName(); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_simple, container, false); } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); Log.d(TAG, "setUserVisibleHint: " + isVisibleToUser); } } 
+7
source

What worked for me, in my pager adapter getItem method, is to save my own link to the returned user fragment in the list. The contract, according to which both the pager fragment adapter and the fragmentation state adapter, seems to mean that the last fragment returned by getItem(i) will be the correct fragment to update in the onPageSelected(i) method.

I tested this method only with a pager fragment adapter and a fairly small number of tabs. Using the pager state adapter will require some testing to make sure that increasing references to fragments leads to increased memory usage.

+1
source

In the FragmentStatePagerAdapter use a HashMap to store created fragments, then you can access them later from the viewpager container (activity or fragment):

 public class CustomFragmentPagerAdapter extends FragmentStatePagerAdapter { private HashMap<Integer, CustomFragment> fragMap = new HashMap<Integer, CustomFragment>(); ... @Override public Fragment getItem(int position) { CustomFragment frag = new CustomFragment(); ... fragMap.put(position, frag); return frag; } @Override public void destroyItem(ViewGroup container, int position, Object object) { super.destroyItem(container, position, object); fragMap.remove(position); } public CustomFragment getFragment(int position) { return fragMap.get(position); } ... } 

Now in your viewpager container (activity or fragment):

 private int lastPage = 0; ... viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { CustomFragment fragment; int currentPage = viewPager.getCurrentItem(); /* connect the current fragment and disconnect the previous one, in case you actually need to disconnect it from the server, otherwise just connect the current fragment.*/ if(currentPage > lastPage) { fragment = yourPagerAdapter.getFragment(currentPage - 1); fragment.disconnect(); fragment = yourPagerAdapter.getFragment(currentPage); fragment.connect(); } else { fragment = yourPagerAdapter.getFragment(currentPage + 1); fragment.disconnect(); fragment = yourPagerAdapter.getFragment(currentPage); fragment.connect(); } lastPage = currentPage; } }); 

Since onPageChangeListener is not called when the application is running, you will need to connect the first fragment. The important thing is that you will have a link to the fragments returned by getItem() using yourPagerAdapter.getFragment(currentPage) .

Edit:

I think this may be the best logic for the onPageSelected() callback method:

 viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { CustomFragment fragment; int currentPage = viewPager.getCurrentItem(); Set<Integer> myKeySet = yourPagerAdapter.getKeys(); for(Integer key : myKeySet) { if(key == currentPage) { fragment = yourPagerAdapter.getFragment(key); fragment.connect(); } else { fragment = yourPagerAdapter.getFragment(key); fragment.disconnect(); } } } }); 

But you need to implement this method on the FragmentStatePagerAdapter :

 public Set<Integer> getKeys() { return fragMap.keySet(); } 

and get rid of the lastPage data lastPage .

0
source

Late to the train. Personally, none of this approach is my favorite. They are hacks. The best way is to use setPrimaryItem(ViewGroup container, int position, Object object) adapters setPrimaryItem(ViewGroup container, int position, Object object)

Inside setPrimaryItem' save the current Fragment and use it inside onPageSelected (end position int) `

An example code looks something like this:

  @Override public void setPrimaryItem(ViewGroup container, int position, Object object) { super.setPrimaryItem(container, position, object); currentFragment = (ProductListFragment) object; } // Inside view pager listener use the currently visible fragment viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(final int position) { currentFragment.onSelected(); // do your thing man } }); 
0
source

Source: https://habr.com/ru/post/969836/


All Articles