FragmentPagerAdapter getItem не запускается

В настоящее время с FragmentActivity я переключаюсь между двумя типами фрагментов, используя следующий код.

private void toggle() {
    Fragment oldFragment = getSupportFragmentManager().findFragmentById(R.id.content);
    Fragment fragment = null;
    if (oldFragment instanceof ColorFragment) {
        fragment = new ViewPagerFragment();
    } else {
        fragment = new ColorFragment(android.R.color.black);
    }

    getSupportFragmentManager().beginTransaction().replace(R.id.content, fragment).commitAllowingStateLoss();
}

2 Фрагмента переключаются.

  • ColorFragment — простой фрагмент, фон которого заливается сплошным черным цветом.
  • ViewPagerFragment — Фрагмент содержит ViewPager. Пользователь может перемещаться между фрагментом фиолетового цвета и фрагментом синего цвета.

Код, который отвечает за смахивание фрагментов фиолетового и синего цветов, приведен ниже.

private static class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    public MyFragmentPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return 2;
    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
        case 0:
            return new ColorFragment(android.R.color.holo_purple);
        default:
            return new ColorFragment(android.R.color.holo_blue_bright);
        }
    }      
} 

Однако я сталкиваюсь со странным поведением во время переключения.

  1. Показан фрагмент черного цвета.
  2. Переключение.
  3. Просмотр пейджера, который может перемещаться между показанными фиолетовыми и синими фрагментами.
  4. Переключение.
  5. Показан фрагмент черного цвета.
  6. Переключение.
  7. Ничего не показано, так как метод getItem MyFragmentPagerAdapter не запускается.

Я думаю, что моя ситуация похожа на FragmentPagerAdapter getItem не вызывается

Однако я предпочитаю не использовать FragmentStatePagerAdapter из-за потенциально больших накладных расходов при переключении между страницами.

Любое обходное решение для решения этой проблемы?

Я привожу полный работоспособный исходный код, чтобы продемонстрировать эту проблему: https://www.dropbox.com/s/jok9tz5ktvfcteo/viewpagerbug.zip


person Cheok Yan Cheng    schedule 23.03.2013    source источник
comment
Я предпочитаю не использовать FragmentStatePagerAdapter — ну, вы хотя бы попробовали его, чтобы увидеть, есть ли разница? из-за потенциально дополнительных накладных расходов при переключении между страницами. - какие потенциально накладные расходы? сценарий, который вы разместили с двумя фрагментами, очень прост.   -  person user    schedule 23.03.2013
comment
@Luksprog Два фрагмента фиолетового и синего цветов предназначены для демонстрации. Фрагменты реальных дел сложнее. Я знаю, что могу сократить определенные накладные расходы, сохранив информацию с помощью пакета или метода сохраненного фрагмента экземпляра. однако я понимаю, что лучший способ избежать накладных расходов в моем случае — избегать использования FragmentStatePagerAdapter.   -  person Cheok Yan Cheng    schedule 23.03.2013


Ответы (5)


Любое обходное решение для решения этой проблемы?

Я скачал ваш код, и проблема возникает из-за того, что вы неправильно обрабатываете эти Fragments. Наиболее точно вы используете вложенный Fragments в ViewPager на основе Fragment и для этого ViewPager вы создаете адаптер следующим образом:

MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter(this.getFragmentManager());

Вместо этого вы должны использовать getChildFragmentManager() для привязки вложенных фрагментов:

MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter(this.getChildFragmentManager());

Кроме того, вы не должны передавать данные через конструктор в Fragment, так как эти данные не сохранятся при изменении конфигурации, и начнут появляться плохие вещи. Вместо этого используйте Bundle.

person user    schedule 23.03.2013
comment
Привет. Действительно спасибо за большую помощь. Однако я не понимаю, почему использование this.getChildFragmentManager решит проблему. Согласно developer.android.com/reference/android/support/ v4/app/, он использует диспетчер фрагментов FragmentActivity через getSupportFragmentManager() (FragmentActivity является владельцем ViewPager). Он не использует диспетчер фрагментов ArrayListFragment (ArrayListFragment(s) — это перелистываемое содержимое ViewPager) - person Cheok Yan Cheng; 23.03.2013
comment
В this.getChildFragmentManager() он возвращает диспетчер фрагментов для фиолетовых и синих фрагментов. Это отличается от официального примера, в котором используется диспетчер фрагментов владельца ViewPager. Следовательно, это меня как-то смущает. - person Cheok Yan Cheng; 23.03.2013
comment
Я не уверен, действительно ли это отвечает на мой собственный вопрос. Я думаю, что приведенный пример является фрагментом внутри активности. Использование getFragmentManager имеет смысл. Однако, если для вложенного фрагмента внутри фрагмента необходимо использовать getChildFragmentManager. Вот как правило, опубликованное Google: developer.android.com/ о/версии/ - person Cheok Yan Cheng; 23.03.2013
comment
@CheokYanCheng getFragmentManager() в вашем примере ViewPagerFragment вернет FragmentManager из Activity (в основном это значение getSupportFragmentmanager() в FragmentActivity, используемое для добавления Fragment). Поскольку вы используете вложенные фрагменты, для них требуется getChildFragmentManager(), чтобы их можно было присоединить к родительскому фрагменту. getFragmentManager() и getChildFragmentManager не одно и то же в Fragment (один возвращает фрагмент, связанный с фрагментом, а другой - менеджер фрагментов, используемый для его вложенных фрагментов). - person user; 23.03.2013
comment
Если бы я мог +1 больше, чем один раз, я бы! Большое спасибо и за ответ, и за объяснение! - person Matthew Clark; 17.04.2014
comment
работает отлично! у меня была такая же проблема с использованием FragmentStatePagerAdapter. - person dy_; 18.09.2014
comment
Большое спасибо. Мне очень помогло.. (у) - person Beena; 24.11.2014
comment
Однако getChildFragmentManager не существует в пакетах поддержки? - person Oliver Dixon; 04.02.2016
comment
@iLoveUnicorns getChildFragmentManager доступен для фрагментов поддержки: разработчик .android.com/reference/android/support/v4/app/ - person user; 04.02.2016
comment
Это идеальное решение. Странно то, что getItem(int pos) все еще не вызывается, но просмотрщик отлично показывает фрагменты! Есть идеи? - person Muhammad Babar; 27.05.2016

Всемирное рабочее проверенное решение.

getSupportFragmentManager() несколько раз сохраняет нулевую ссылку, а просмотр пейджера не создает новый экземпляр фрагмента. Поскольку он находит ссылку на тот же фрагмент. Таким образом, чтобы преодолеть это использование, getChildFragmentManager() решает проблему простым способом.

Не

new PagerAdapter(getSupportFragmentManager(), fragments);

Выполнить

new PagerAdapter(getChildFragmentManager() , fragments);

person Vinayak    schedule 28.01.2015
comment
Отличное объяснение. Спасибо - person Desmond Lee; 01.09.2015

В моем случае я правильно звонил

MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter(this.getChildFragmentManager());

но затем во вложенном фрагменте я пытался заменить фрагмент контейнера другим, используя:

getFragmentManager()

Вам нужно зайти на мероприятие и позвонить

getActivity().getSupportFragmentManager();
person kingston    schedule 11.11.2015

Простое использование FragmentStatePagerAdapter вместо FragmentPagerAdapter

or

вы можете использовать new MyFragmentPagerAdapter(this.getChildFragmentManager())

Надеюсь, это поможет вам :)

person Neo    schedule 20.06.2016

В моих случаях это сработало после добавления этого в мой FragmentPagerAdapter:

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

и я также использовал getChildFragmentManager(), как сказал Luksprog

person Jorge Casariego    schedule 28.04.2016