Переход к фрагментам FragmentPagerAdapter → пустым
У меня есть фрагмент (я назову его pagerFragment
), который будет добавлен в стопку и будет виден. Он содержит a viewPager
с a FragmentPagerAdapter
. FragmentPagerAdapter
содержит (скажем) два фрагмента: A и B.
Первое добавление фрагментов отлично работает.
Фрагмент A имеет кнопку, которая когда-то нажата, добавляет фрагмент (C) к стопке назад.
Проблема заключается в следующем: если я добавлю этот фрагмент (C), а затем вернусь назад, pagerAdapter
пуст, и я не вижу никаких фрагментов внутри.
Если я использую взломать и уничтожу фрагменты детей (A и B) в pagerFragment
onDestroyView()
, это решает проблему, хотя я не хочу использовать этот хак.
Какие идеи могут возникнуть?
Ответы
Ответ 1
У меня была та же проблема. Решение для меня было простым:
в onCreateView у меня было:
// Create the adapter that will return a fragment for each of the three
// primary sections of the app.
mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity()
.getSupportFragmentManager());
где SectionPageAdapter выглядит примерно так:
class SectionsPagerAdapter extends FragmentPagerAdapter {
...
}
после изменения getSupportFragmentManager на
mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
он начал работать!
Надеюсь, это поможет.
Ответ 2
Похоже, вы используете вложенные фрагменты, так как ваш ViewPager находится внутри PagerFragment. Вы передали getChildFragmentManager() в конструктор вашего FragmentPagerAdapter? Если нет, вы должны.
Я не думаю, что вам нужен FragmentStatePagerAdapter, но я бы дал этот снимок, так как он обрабатывает сохранение и восстановление состояния фрагмента. Тот факт, что ваш рабочий процесс onDestroyView() заставляет меня думать, что вам может понадобиться FragmentStatePagerAdapter.
Он также может иметь какое-то отношение к тому, как FragmentPagerAdapter добавляет фрагменты. FragmentPagerAdapter не добавляет фрагменты в стопку. Представьте себе, что в вашем ViewPager было добавлено более 10 страниц, и пользователь проскочил через них. Пользователю нужно будет ударить 11 раз, чтобы вернуться из приложения.
Он также может быть связан с этим сообщением: Вложенные фрагменты и Back Stack.
Также я не уверен, что вы добавляете фрагмент C в. Вы добавляете его в тот же контейнер, что и ViewPager?
Хорошо, по крайней мере, у вас есть несколько вариантов для исследования. В этих ситуациях мне нравится отлаживать исходный код Android SDK и видеть, что вызывает поведение. Я рекомендую захватить источник AOSP и добавить фреймворки/поддержку и фреймворки/базу в качестве источников SDK. Это единственный истинный способ понять, что происходит, и избегать случайных изменений до тех пор, пока все не сработает.
Ответ 3
Я просто столкнулся с проблемой в нашем проекте. Основная причина заключается в том, как работает FragmentPagerAdapter:
FragmentPagerAdapter просто отделяет фрагмент, который в настоящее время не нужен из его представления, но не удаляет его из FragmentManager. Когда он захочет снова отобразить фрагмент, он посмотрит, сохраняет ли FragmentManager Фрагмент с использованием тега, который создается из идентификатора вида ViewPager и идентификатора, возвращаемого вызовом getItemId (position) адаптера. Если он найдет фрагмент, он просто планирует привязать фрагмент к его представлению в транзакции обновления FragmentManager. Только если он не найдет фрагмент таким образом, он создает новый, используя вызов адаптера getItem (position)!
Проблема с фрагментом, содержащим ViewPager с FragmentPagerAdapter, заключается в том, что содержимое FragmentManager никогда не очищается, когда содержащийся фрагмент помещается в задний стек. Если содержащий фрагмент возвращается из заднего стека, он создает новый View, но FragmentManager все еще содержит фрагменты, которые были прикреплены к старому представлению, и прикрепление существующего фрагмента больше не работает.
Самый простой способ избавиться от этой проблемы - избежать вложенных фрагментов.:)
Второй самый простой способ, как уже упоминалось в других сообщениях, использовать ChildFragmentManager для FragmentPagerAdapter, так как он правильно обновляется в течение жизненного цикла фрагмента контейнера.
Как есть проекты (как мои текущие), где оба варианта невозможны, я опубликовал здесь решение, которое работает с произвольным FragmentManager, используя hashCode субфрагментов как идентификатор элемента фрагмента в этой позиции, Это связано с ценой хранения всех фрагментов для всех позиций в адаптере.
public class MyPagerAdapter extends FragmentPagerAdapter {
private static int COUNT = ...;
private final FragmentManager fragmentManager;
private Fragment[] subFragments = new Fragment[COUNT];
private FragmentTransaction cleanupTransaction;
public MyPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
this.fragmentManager = fragmentManager;
}
@Override
public Fragment getItem(int position) {
return getSubFragmentAtPosition(position);
}
@Override
public int getCount() {
return COUNT;
}
@Override
public long getItemId(int position) {
return getSubFragmentAtPosition(position).hashCode();
}
//The next three methods are needed to remove fragments no longer used from the fragment manager
@Override
public void startUpdate(ViewGroup container) {
super.startUpdate(container);
cleanupTransaction = fragmentManager.beginTransaction();
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
cleanupTransaction.remove((Fragment) object);
}
@Override
public void finishUpdate(ViewGroup container) {
super.finishUpdate(container);
cleanupTransaction.commit();
}
private Fragment getSubFragmentAtPosition(int position){
if (subFragments[position] == null){
subFragments[position] = ...;
}
return subFragments[position];
}
}
Ответ 4
Используйте getChildFragmentManager()
вместо getSupportFragmentManager()
.
Он будет работать нормально.