Я только что столкнулся с проблемой в нашем проекте. Основная причина заключается в том, как работает FragmentPagerAdapter:
FragmentPagerAdapter просто отсоединяет фрагмент, который ему в данный момент не нужен, из своего представления, но не удаляет его из своего FragmentManager. Когда он хочет снова отобразить фрагмент, он проверяет, содержит ли FragmentManager фрагмент, используя тег, созданный из идентификатора представления ViewPager и идентификатора, возвращаемого вызовом адаптера getItemId(position). Если он находит фрагмент, он просто планирует присоединение фрагмента к его представлению в рамках транзакции обновления FragmentManager. Только если он не находит Фрагмент таким образом, он создает новый, используя вызов адаптера getItem(position)!
Проблема с фрагментом, содержащим ViewPager с FragmentPagerAdapter, заключается в том, что содержимое FragmentManager никогда не очищается, когда содержащий фрагмент помещается в задний стек. Если содержащий фрагмент возвращается из заднего стека, он создает новое представление, но FragmentManager по-прежнему содержит фрагменты, которые были прикреплены к старому представлению, и присоединение существующего фрагмента больше не работает.
Самый простой способ избавиться от этой проблемы — избегать вложенных фрагментов. :)
Второй самый простой способ, как уже упоминалось в других сообщениях, заключается в использовании ChildFragmentManager для FragmentPagerAdapter, поскольку он правильно обновляется в течение жизненного цикла фрагмента контейнера.
Поскольку есть проекты (как мой текущий), где оба варианта невозможны, я опубликовал здесь решение, которое работает с произвольным FragmentManager, используя хэш-код подфрагментов в качестве идентификатора элемента фрагмента в этой позиции. Это происходит за счет хранения всех фрагментов для всех позиций в адаптере.
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];
}
}
person
Nantoka
schedule
21.11.2017