FragmentPagerAdapter getItem не викликається


123

Я не в змозі повторно використовувати фрагмент у FragmentPagerAdapter .. Використовуючи метод killItem (), він видаляє фрагмент, але все ще не викликає 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)); 

3
Чи є певна причина, що ви перестаралися destroyItem()? Це не обов'язково.
CommonsWare

щоб знову ініціалізувати, використовуйте FragmentStatePagerAdapter також дзвінок, коли ви перекриєте його super.destroyItem (контейнер, позиція, об'єкт);
faiziii

Відповіді:


306

Відповідь KISS:

Просте використання FragmentStatePagerAdapter замість FragmentPagerAdapter .

Я отримав відповідь. По-перше, я подумав видалити це питання, оскільки роблю дуже дурну помилку, але ця відповідь допоможе тому, хто стикається з тією ж проблемою, яку замість цього FragmentPagerAdapterвикористовують FragmentStatePagerAdapter.

Як в коментарі згадував @BlackHatSamurai:

Причина цього працює в тому, що FragmentStatePagerAdapterруйнує як фрагменти, які не використовуються. FragmentPagerAdapterне.


Дуже дякую. Ваша відповідь допомогла мені багато.
Прия

1
Ненавиджу бути черговим "я теж!" повідомлення, але так>. <Дякуємо, що не видалили питання.
Пол Руїс

34
Причина цього працює в тому, що FragmentStatePagerAdapter знищує як фрагменти, які не використовуються. FragmentPagerAdapter ні.
BlackHatSamurai

3
Просто для подальшого ознайомлення для тих, хто може виявити це під час пошуку конкретної проблеми, яка у них є; читати як на FragmentPagerAdapter, так і на FragmentStatePagerAdapter. Вони поводяться по-різному з причини, і ваше конкретне використання може зажадати одне за іншим.
Кріс Стюарт

2
@najibputhawala Я використав FragmentStatePagerAdapter, але все ще стикався з тією ж проблемою. getItem () не називається
sam_k

168

Використання FragmentStatePagerAdapterне повністю виправили мою проблему, яка була аналогічною проблемою, коли onCreateViewне було викликано дочірніх фрагментів у пейджері перегляду. Я фактично гніздую свою FragmentPagerAdapterіншу внутрішню частину,Fragment тому FragmentManagerспільне для всіх було збережене, таким чином зберігаючи екземпляри старих фрагментів. Виправлення полягало в тому, щоб замість цього подати екземпляр getChildFragmentManagerконструктора FragmentPagerAdapterв моєму фрагменті хоста. Щось на зразок...

FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());

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

  • Але майте на увазі, щоб використовувати getChildFragmentManager()вашу мінімальну версію API, потрібно якнайменше 17 (4.2), тому це може закинути гайковий ключ у ваші передачі. Звичайно, якщо ви використовуєте фрагменти з бібліотеки підтримки v4, вам слід добре.

25
Це правильна відповідь. Проблема пов'язана з тим, що фрагменти, вкладені в інші фрагменти, повинні використовувати getChildrenFragmentManager () замість getFragmentManager ().
shihpeng

Дуже дякую, мені знадобилося назавжди знайти цю відповідь!
Шпонголоїд

Я згоден з @shihpeng. Це має бути правильна відповідь.
Раймонд Луканта

Це було для мене виправкою. Дякую за подання відповіді
user3734429

Документи дійсно повинні викликати це в ході. Цілком реально, що ViewPager буде завантажений у фрагмент. Дякуємо, що опублікували цю відповідь.
працював

7

Переосмислити long getItemId (int position)

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

Це насправді особливість, а не помилка. Вам потрібно переосмислити, getItemIdщоб ви могли правильно використовувати свої фрагменти. Оскільки ви видаляєте фрагменти, ваші позиції змінюються. Як зазначено в документах:

long getItemId (int position)

Поверніть унікальний ідентифікатор для елемента в заданій позиції.

За замовчуванням реалізація повертає задану позицію. Підкласи повинні замінити цей метод, якщо позиції елементів можуть змінюватися.

Просто надайте унікальний ідентифікатор кожному фрагменту, і ви закінчите

Використання FragementStatePagerAdapterабо повернення POSITION_NONEв int getItemPosition (Object object)неправильно. Ви не отримаєте кешування.


Ця відповідь була правильною. Я повинен був надати різні ідентифікатори для фрагментів у getItemIdAND, getItemPositionщоб повернути, POSITION_NONEякщо ІЧ фрагмент слід видалити. У мене є прапор переліку. Після цього getItemбуде називатися.
Мурат Карагез

Дякую @ MuratKaragöz за +50 :)
продавець

5

Я зробив те, що опублікував @kanika та @ Jraco11, але у мене все-таки виникли проблеми.

Отже, після багатьох змін я знайшов той, який працював на мене і був доданий до мого FragmentPagerAdapter наступний код:

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

Згідно з тим, що я прочитав, getItemPosition використовується для сповіщення ViewPager про те, чи потрібно оновити елемент, а також уникнути оновлень, якщо елементи на видимих ​​позиціях не змінилися.


2

Є два різні сценарії: 1.) У вас однаковий макет для кожного пейджера: У такому випадку буде краще, якщо ви розширите свій власний адаптер на PagerAdapter і повернете один макет.

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


2

метод getItem()використовується лише для створення нових елементів. Після їх створення цей метод не буде називатися. Якщо вам потрібно отримати товар, який використовує адаптер, використовуйте цей метод:

pagerAdapter.instantiateItem(viewPager, TAB_POS)

0

Я виявив, що встановлення слухача на макет вкладки зупинило це на виклику, ймовірно, тому, що у них є місце лише для одного слухача, tabLayout.setOnTabSelectedListenerа не для маси слухачів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.