Я считаю, что FragmentStatePagerAdapter неправильно ведет себя при переопределении getItemPosition(Object object)
с целью переупорядочения страниц.
Ниже приведен простой пример. В начальном состоянии порядок страниц - {A, B, C}. При вызове toggleState()
порядок страниц изменяется на {A, C, B}. Переопределяя getItemPosition(Object object)
, мы гарантируем, что текущая страница, просматриваемая (A, B или C), не изменяется.
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));
}
}
Я столкнулся с двумя отдельными типами поведения, которые кажутся неправильными.
-
Если я сразу вызову
toggleState()
(во время просмотра страницы A, перед тем, как перейти на любую другую страницу), приложение выйдет из строя.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) ...
Посмотрев на источник
FragmentStatePagerAdapter
, это будет исправлено, сначала проверив размерmFragments
(как в строках 113-115), прежде чем вызыватьset()
в строке 136. -
Если я сначала провёл страницу B, вызывается
getItem(2)
, создается страница C, аmFragments
теперь имеет размер 3 (это предотвратит мгновенное появление сбоя). Затем я вернусь на страницу A, и страница C будет уничтожена, как и должно быть (поскольку она находится на расстоянии 2 страницы, и я использую ограничение по умолчанию для экрана на 1). Теперь я называюtoggleState()
. Страница B теперь уничтожена. Однако страница C НЕ воссоздана! Это означает, что когда я теперь прокручиваю вправо, я получаю пустую страницу.
Во-первых, было бы неплохо узнать, правильно ли я, и на самом деле это ошибки, или я делаю что-то неправильно. Если они являются ошибками, может ли кто-нибудь предложить обходное решение (кроме отладки и перестройки библиотеки поддержки)? Разумеется, кто-то должен был успешно переопределить getItemPosition(Object object)
(кроме того, что все установлено на POSITION_NONE
)?
Я использую текущую версию (10) библиотеки поддержки.