Note that there are some explanatory texts on larger screens.

plurals
  1. POreorder pages in FragmentStatePagerAdapter using getItemPosition(Object object)
    text
    copied!<p>I believe that FragmentStatePagerAdapter does not behave correctly when overriding <code>getItemPosition(Object object)</code> with the purpose of reordering the pages.</p> <p>Below is a simple example. In the initial state, the order of the pages is {A, B, C}. Upon calling <code>toggleState()</code>, the order of the pages changes to {A, C, B}. By overriding <code>getItemPosition(Object object)</code>, we ensure that the current page being viewed (A, B, or C) does not change.</p> <pre><code>public static class TestPagerAdapter extends FragmentStatePagerAdapter { private boolean mState = true; public TestPagerAdapter(FragmentManager fragmentManager) { super(fragmentManager); } @Override public int getCount() { return 3; } private void toggleState() { mState = !mState; notifyDataSetChanged(); } private String getLabel(int position) { switch (position) { case 0: return "A"; case 1: return mState ? "B" : "C"; default: return mState ? "C" : "B"; } } @Override public int getItemPosition(Object object) { String label = ((TestFragment) object).getLabel(); if (label.equals("A")) { return 0; } else if (label.equals("B")) { return mState ? 1 : 2; } else { return mState ? 2 : 1; } } @Override public CharSequence getPageTitle(int position) { return getLabel(position); } @Override public Fragment getItem(int position) { return TestFragment.newInstance(getLabel(position)); } } </code></pre> <p>I have encountered two separate behaviours which seem incorrect.</p> <ol> <li><p>If I immediately call <code>toggleState()</code> (while viewing page A, before swiping to any other page), the app crashes.</p> <pre><code>java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2 at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251) at java.util.ArrayList.set(ArrayList.java:477) at android.support.v4.app.FragmentStatePagerAdapter.destroyItem(FragmentStatePagerAdapter.java:136) at android.support.v4.view.ViewPager.populate(ViewPager.java:867) at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:469) at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:441) at android.support.v4.view.ViewPager.dataSetChanged(ViewPager.java:766) at android.support.v4.view.ViewPager$PagerObserver.onChanged(ViewPager.java:2519) at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37) at android.support.v4.view.PagerAdapter.notifyDataSetChanged(PagerAdapter.java:276) at com.ugglynoodle.test.testfragmentstatepageradapter.MainActivity$TestPagerAdapter.toggleState(MainActivity.java:55) ... </code></pre> <p>Looking at the source of <code>FragmentStatePagerAdapter</code>, this would be fixed by first checking the size of <code>mFragments</code> (as in lines 113-115) before calling <code>set()</code> in line 136.</p></li> <li><p>If I first swipe to page B, then <code>getItem(2)</code> is called, page C is created, and <code>mFragments</code> now has a size of 3 (this will prevent the crash above from happening in a moment). Then I swipe back to page A, and page C is destroyed, as it should be (since it is 2 pages away, and I'm using the default offscreen page limit of 1). Now, I call <code>toggleState()</code>. Page B is now destroyed. However, page C is NOT recreated! This means, when I now swipe to the right, I get an empty page.</p></li> </ol> <p>First, it would be nice to know whether I'm correct and these are in fact bugs, or whether I'm doing something wrong. If they are bugs, can anyone suggest a workaround (other than debugging and rebuilding the support library myself)? Surely somebody must have overridden <code>getItemPosition(Object object)</code> successfully (apart from setting everything to <code>POSITION_NONE</code>)?</p> <p>I am using the current revision (10) of the support library.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload