it-swarm.com.ru

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)); 
108
Kanika

KISS Ответ:

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

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

Как отметил @BlackHatSamurai в комментарии:

Это работает потому, что FragmentStatePagerAdapter уничтожает как фрагменты, которые не используются. FragmentPagerAdapter нет.

280
Kanika

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

FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());

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

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

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

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

2
Maddy

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

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

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

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

2
Jorge Casariego

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

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

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

long getItemId (int position)

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

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

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

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

1
vedant

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

0
Oliver Dixon

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

pagerAdapter.instantiateItem(viewPager, TAB_POS)
0
B-GangsteR