Ответ 1
Это может помочь -
@Override
public Parcelable saveState() {
return null;
}
Добавьте строку выше в FragmentStatePagerAdapter
.
Я хочу понять это исключение, чтобы осуществить правильное исправление.
Есть ViewPager, и он использует FragmentStatePagerAdapter для создания экземпляров 2-х фрагментов через getItem и MyFragmentClass.newInstance(...)
.
Адаптер getItem выглядит так:
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch(position) {
case 0:
fragment = MyFragment2.newInstance(par1);
break;
case 1:
fragment = MyFragment2.newInstance(par2, par3);
break;
}
return fragment;
}
Проблема:
Когда действие уничтожается и создается снова, адаптер снова создается, фрагменты создаются снова с помощью MyFragmentClass.newInstance(...)
... но затем в этой строке:
pager.setAdapter(adapter);
Я получаю упомянутое исключение.
Я посмотрел в источнике, где выбрасывается исключение, это:
@Override
public Fragment getFragment(Bundle bundle, String key) {
int index = bundle.getInt(key, -1);
if (index == -1) {
return null;
}
if (index >= mActive.size()) {
throw new IllegalStateException("Fragement no longer exists for key "
+ key + ": index " + index);
}
Fragment f = mActive.get(index);
if (f == null) {
throw new IllegalStateException("Fragement no longer exists for key "
+ key + ": index " + index);
}
return f;
}
Таким образом, пакет передается туда с некоторым состоянием, которое ссылается на мои старые фрагменты, но это не соответствует текущему состоянию (mActive
), и mActive
исключение.
Я не понимаю, в чем суть этой идеи или каким образом я должен создавать фрагменты.
Я попробовал трюк, полученный из другого контекста:
pager.setOffscreenPageLimit(1);
Во избежание того, что фрагменты уничтожаются, когда они находятся за пределами экрана (в случае 2-страничного видового пейджера, хотя не знаю, хорошо ли он работает с адаптером состояния). Но, похоже, это не связано, по крайней мере, это не помогает, но все равно получаю то же исключение.
Перехват исключения приводит к тому, что страницы остаются пустыми.
Это может помочь -
@Override
public Parcelable saveState() {
return null;
}
Добавьте строку выше в FragmentStatePagerAdapter
.
Если вы не хотите, чтобы фрагменты были восстановлены, когда они за кадром, вы должны использовать FragmentPagerAdapter
, а не FragmentStatePagerAdapter
.
Сведения о выпуске
По умолчанию FragmentStatePagerAdapter сохранит и восстановит состояние ViewPager. При восстановлении, если экземпляр фрагмента уничтожен по какой-либо причине, FragmentManger выдаст это исключение.
Решение:
Чтобы это исправить, нужно переопределить метод restoreState в нашем FragmentStatePagerAdapter и поставить блок try catch. Это предотвратит сбой, а также сохранит состояние фрагмента окна просмотра для обычного случая.
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
try {
super.restoreState(state, loader);
} catch (Exception e) {
Log.e("TAG", "Error Restore State of Fragment : " + e.getMessage(), e);
}
}
Примечание. Мы можем использовать FragmentPagerAdapter или Override saveState() и возвращать значение null, также исправляя эту проблему, но viewpager не будет сохранять свое состояние для обычного случая.
У меня есть борьба по этой проблеме на целый день, но теперь я нашел решение.
private ViewPager _mViewPager;
_mViewPager.setOffscreenPageLimit(5);
//5 is how much page you have.
setOffscreenPageLimit
Задайте количество страниц, которые должны быть сохранены в обе стороны текущей страницы иерархии представлений в состоянии ожидания. Страницы, выходящие за этот предел, будут воссозданы из адаптера, если это необходимо.
Очень хорошо! Поскольку repeat pager.setAdapter(adapter);
, когда вызов restoreState
вызывает исключение:
Fragment no longer exists for key f0: index 0
мы можем вывести фрагмент RootView
public void onDestroyView() {
super.onDestroyView();
if (isRecyclerRootViewAlways()) {
mRootView = null;//<--
}
mMyFragmentLifecycle.onFragmentDestroyView(this);
}
использование
getFragmentManager()
во фрагментном адаптере не дочерний фрагментный менеджер
PagerAdapter adapter = new PagerAdapter(getFragmentManager());
Надеюсь, это поможет.