FragmentPagerAdapter getItem не вызывается

Я не могу повторно использовать фрагмент в FragmentPagerAdapter.. Используя метод destroyItem(), он удаляет фрагмент, но все еще не называется getItem() снова.. Есть только 2-3 изображения, поэтому я использую FragmentPagerAdapter Вместо FragmentStatePagerAdapter..

public class ExamplePagerAdapter extends FragmentPagerAdapter {

    ArrayList < String > urls;
    int size = 0;
    public ExamplePagerAdapter(FragmentManager fm, ArrayList < String > res) {
        super(fm);
        urls = res;
        size = urls.size();
    }

    @Override
    public int getCount() {
        if (urls == null) {
            return 0;
        } else {
            return size;
        }

    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        FragmentManager manager = ((Fragment) object).getFragmentManager();
        FragmentTransaction trans = manager.beginTransaction();
        trans.remove((Fragment) object);
        trans.commit();
    }

    @Override
    public Fragment getItem(int position) {

        Fragment fragment = new FloorPlanFragment();
        Bundle b = new Bundle();
        b.putInt("p", position);
        b.putString("image", urls.get(position));
        Log.i("image", "" + urls.get(position));
        fragment.setArguments(b);
        return fragment;
    }
}

И в FragmentActivity,

pager.setAdapter(new ExamplePagerAdapter(getSupportFragmentManager(), res2)); 

Ответ 1

Ответ KISS:

Просто используйте FragmentStatePagerAdapter вместо FragmentPagerAdapter.

Я получил ответ. Сначала я решил удалить этот вопрос, поскольку я делаю очень глупую ошибку, но этот ответ поможет кому-то, кто сталкивается с той же проблемой, что вместо FragmentPagerAdapter используйте FragmentStatePagerAdapter.

Как @BlackHatSamurai упоминается в комментарии:

Причина этого в том, что FragmentStatePagerAdapter уничтожает как Фрагменты, которые не используются. FragmentPagerAdapter нет.

Ответ 2

Использование FragmentStatePagerAdapter не полностью устранило мою проблему, которая была аналогичной проблемой, когда onCreateView не вызывался для дочерних фрагментов в представлении пейджера. Я на самом деле , размещая мой FragmentPagerAdapter внутри другого Fragment, поэтому FragmentManager был общим для всех из них и, таким образом, сохранял экземпляры старых фрагментов. Исправление состояло в том, чтобы вместо этого передать экземпляр getChildFragmentManager в конструктор FragmentPagerAdapter в моем фрагменте хоста. Что-то вроде...

FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());

Метод getChildFragmentManager() доступен через фрагмент, и это сработало для меня, потому что оно возвращает частный FragmentManager для этого фрагмента специально для ситуаций, в которых требуется вложение фрагментов. Я надеюсь, что это поможет кому-то, у кого может быть такая же проблема, что и я!

  • Имейте в виду, однако, чтобы использовать getChildFragmentManager(), ваша минимальная версия API должна быть как минимум 17 (4.2), поэтому это может привести к гаечным ключам в ваших передачах. Конечно, если вы используете фрагменты из библиотеки поддержки v4, вы должны быть в порядке.

Ответ 3

Существует два разных сценария: 1.) У вас одинаковый макет для каждого пейджера:       В этом случае будет лучше, если вы расширите свой пользовательский адаптер       PagerAdapter и вернуть один макет.

2.) У вас разный макет для каждого пейджера:       В этом случае будет лучше, если вы расширите свой пользовательский адаптер       FragmentStatePagerAdapter и возвращать различные фрагменты для каждого пейджера.

Ответ 4

Я сделал то, что @kanika и @Jraco11 опубликовали, но у меня все еще была проблема.

Итак, после многих изменений я нашел тот, который работал у меня, и был добавлен в мой FragmentPagerAdapter следующий код:

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

В соответствии с тем, что я прочитал, getItemPosition используется, чтобы уведомить ViewPager, обновлять или не обновлять элемент, а также избегать обновлений, если элементы в видимых позициях Не изменилось.

Ответ 5

Переопределить long getItemId (int position)

FragmentPagerAdapter кэширует фрагменты, getItem с помощью getItem. Я столкнулся с тем же issue- даже после вызова notifyDataSetChanged() getItem не вызывался.

Это на самом деле функция, а не ошибка. Вам необходимо переопределить getItemId чтобы вы могли правильно использовать свои фрагменты. Поскольку вы удаляете фрагменты, ваши позиции меняются. Как упоминалось в документах:

long getItemId (int position)

Возвращает уникальный идентификатор элемента в заданной позиции.

Реализация по умолчанию возвращает заданную позицию. Подклассы должны переопределять этот метод, если позиции элементов могут измениться.

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

Использование FragementStatePagerAdapter или возврат POSITION_NONE в int getItemPosition (Object object) неверно. Вы не получите никакого кэширования.

Ответ 6

Я обнаружил, что установка прослушивателя на макете табуляции остановила это от вызова, вероятно, потому что у них есть только место для одного прослушивателя на tabLayout.setOnTabSelectedListener вместо массива слушателей.