Подтвердить что ты не робот

Переход к фрагментам FragmentPagerAdapter → пустым

У меня есть фрагмент (я назову его pagerFragment), который будет добавлен в стопку и будет виден. Он содержит a viewPager с a FragmentPagerAdapter. FragmentPagerAdapter содержит (скажем) два фрагмента: A и B.

Первое добавление фрагментов отлично работает.

Фрагмент A имеет кнопку, которая когда-то нажата, добавляет фрагмент (C) к стопке назад.

Проблема заключается в следующем: если я добавлю этот фрагмент (C), а затем вернусь назад, pagerAdapter пуст, и я не вижу никаких фрагментов внутри.

Если я использую взломать и уничтожу фрагменты детей (A и B) в pagerFragment onDestroyView(), это решает проблему, хотя я не хочу использовать этот хак.

Какие идеи могут возникнуть?

4b9b3361

Ответ 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(). Он будет работать нормально.