Как получить существующие фрагменты при использовании FragmentPagerAdapter

99

У меня проблема с тем, чтобы мои фрагменты взаимодействовали друг с другом через класс Activity, который использует FragmentPagerAdapter, в качестве вспомогательного класса, который реализует управление вкладками и всеми деталями подключения к ViewPagerсвязанному TabHost. Я реализовал то FragmentPagerAdapterже самое, что и в образце проекта Android Support4Demos .

Главный вопрос: как получить конкретный фрагмент, FragmentManagerесли у меня нет ни идентификатора, ни тега? FragmentPagerAdapterсоздает фрагменты и автоматически генерирует идентификатор и теги.

Исмар Сломич
источник
@ jk2K, как это может быть дубликатом вопроса, который был задан год спустя,
Дэви
@Dawit дублируется как ярлык, не связанный со временем, более поздние вопросы имеют более высокие просмотры
jk2K
Большинство ответов здесь не работают в производственной
среде

Ответы:

194

Краткое изложение проблемы

Примечание. В этом ответе я буду ссылаться на FragmentPagerAdapterего исходный код. Но общее решение также должно применяться к FragmentStatePagerAdapter.

Если вы читаете это, вы, вероятно, уже знаете, что FragmentPagerAdapter/ FragmentStatePagerAdapterпредназначен для создания Fragmentsдля вас ViewPager, но при воссоздании Activity (будь то вращение устройства или система, убивающая ваше приложение для восстановления памяти) они Fragmentsне будут созданы снова, а вместо этого их экземпляры, извлеченные изFragmentManager . Теперь скажите, что вам Activityнужно получить ссылку на них, Fragmentsчтобы поработать над ними. У вас нет созданных idили tagдля них, Fragmentsпотому что они FragmentPagerAdapter установлены внутри . Итак, проблема в том, как получить на них ссылку без этой информации ...

Проблема с текущими решениями: полагаться на внутренний код

Многие из решений , которые я видел на этом и подобных вопросах рассчитывать на получение ссылки на существующий Fragmentпо телефону FragmentManager.findFragmentByTag()и имитируя внутренне созданный тег:"android:switcher:" + viewId + ":" + id . Проблема в том, что вы полагаетесь на внутренний исходный код, который, как мы все знаем, не гарантирует, что он останется неизменным навсегда. Инженеры Android в Google могут легко решить изменить tagструктуру, которая сломает ваш код, и вы не сможете найти ссылку на существующий Fragments.

Альтернативное решение, не полагаясь на внутренние tag

Вот простой пример того, как получить ссылку на Fragmentsвозвращаемый объект FragmentPagerAdapter, который не зависит от внутреннего tagsнабора в Fragments. Ключ в том, чтобы переопределить instantiateItem()и сохранить ссылки там, а не в getItem().

public class SomeActivity extends Activity {
    private FragmentA m1stFragment;
    private FragmentB m2ndFragment;

    // other code in your Activity...

    private class CustomPagerAdapter extends FragmentPagerAdapter {
        // other code in your custom FragmentPagerAdapter...

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

        @Override
        public Fragment getItem(int position) {
            // Do NOT try to save references to the Fragments in getItem(),
            // because getItem() is not always called. If the Fragment
            // was already created then it will be retrieved from the FragmentManger
            // and not here (i.e. getItem() won't be called again).
            switch (position) {
                case 0:
                    return new FragmentA();
                case 1:
                    return new FragmentB();
                default:
                    // This should never happen. Always account for each position above
                    return null;
            }
        }

        // Here we can finally safely save a reference to the created
        // Fragment, no matter where it came from (either getItem() or
        // FragmentManger). Simply save the returned Fragment from
        // super.instantiateItem() into an appropriate reference depending
        // on the ViewPager position.
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
            // save the appropriate reference depending on position
            switch (position) {
                case 0:
                    m1stFragment = (FragmentA) createdFragment;
                    break;
                case 1:
                    m2ndFragment = (FragmentB) createdFragment;
                    break;
            }
            return createdFragment;
        }
    }

    public void someMethod() {
        // do work on the referenced Fragments, but first check if they
        // even exist yet, otherwise you'll get an NPE.

        if (m1stFragment != null) {
            // m1stFragment.doWork();
        }

        if (m2ndFragment != null) {
            // m2ndFragment.doSomeWorkToo();
        }
    }
}

или если вы предпочитаете работать с tagsпеременными-членами класса или ссылками на них, Fragmentsвы также можете получить tagsнабор FragmentPagerAdapterтаким же образом: ПРИМЕЧАНИЕ: это не относится к, FragmentStatePagerAdapterпоскольку оно не устанавливается tagsпри создании его Fragments.

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
    // get the tags set by FragmentPagerAdapter
    switch (position) {
        case 0:
            String firstTag = createdFragment.getTag();
            break;
        case 1:
            String secondTag = createdFragment.getTag();
            break;
    }
    // ... save the tags somewhere so you can reference them later
    return createdFragment;
}

Обратите внимание, что этот метод НЕ полагается на имитацию внутреннего tagнабора, FragmentPagerAdapterа вместо этого использует соответствующие API для их получения. Таким образом, даже если tagизменения в будущих версиях SupportLibraryвы все равно будете в безопасности.


Не забывайте, что в зависимости от вашего дизайна Activity, то, над Fragmentsчем вы пытаетесь работать, может еще существовать, а может и не существовать, поэтому вы должны учесть это, выполнив nullпроверки перед использованием ваших ссылок.

Кроме того, если вместо этого вы работаете с FragmentStatePagerAdapterвами, вы не хотите хранить жесткие ссылки на свои, Fragmentsпотому что у вас может быть их много, и жесткие ссылки излишне сохранят их в памяти. Вместо этого сохраните Fragmentссылки в WeakReferenceпеременных вместо стандартных. Как это:

WeakReference<Fragment> m1stFragment = new WeakReference<Fragment>(createdFragment);
// ...and access them like so
Fragment firstFragment = m1stFragment.get();
if (firstFragment != null) {
    // reference hasn't been cleared yet; do work...
}
Тони Чан
источник
3
Это действительно хорошее решение, но оно, похоже, теряет свою эффективность, если вы не знаете, сколько фрагментов будет передано.
Riot Goes Woof
3
@Zorpix, вы можете хранить созданные фрагменты в HashMap: map.put (position, createdFragment);
Том Бевеландер,
12
Это заслуживает галочки! Очень умный и комплексный способ добиться этого. Вы мне очень помогли, спасибо!
young_souvlaki
2
Сначала это решение выглядело слишком сложным, поэтому я его пропустил. Я наконец вернулся к этому, потому что другие ответы не были удовлетворительными. И это было не так сложно, как я думал.
Suragch
1
не нужно ничего переопределять, и вы на самом деле не должны переопределять instantiateItem. правильный способ сделать это, чтобы позвонить instantiateItem в onCreateметоде вашей деятельности в окружении startUpdateи finishUpdate. Подробности смотрите в моем ответе
morgwai
82

Я нашел ответ на свой вопрос на основе следующего сообщения: повторное использование фрагментов в fragmentpageradapter

Я кое-что узнал:

  1. getItem(int position)в FragmentPagerAdapterдовольно вводящем в заблуждение названии того, что на самом деле делает этот метод. Он создает новые фрагменты, не возвращая существующие. В этом смысле метод следует переименовать во что-то вроде createItem(int position)Android SDK. Таким образом, этот метод не помогает нам получать фрагменты.
  2. Основываясь на объяснении в пост- поддержке, FragmentPagerAdapter держит ссылку на старые фрагменты, вы должны оставить создание фрагментов на FragmentPagerAdapterи, таким образом, у вас нет ссылки на фрагменты или их теги. Если у вас есть тег фрагмента, вы можете легко получить ссылку на него из FragmentManagerкласса, вызвав findFragmentByTag(). Нам нужен способ узнать тег фрагмента в заданной позиции страницы.

Решение

Добавьте следующий вспомогательный метод в свой класс, чтобы получить тег фрагмента и отправить его findFragmentByTag()методу.

private String getFragmentTag(int viewPagerId, int fragmentPosition)
{
     return "android:switcher:" + viewPagerId + ":" + fragmentPosition;
}

НОТА! Это тот же метод, что и FragmentPagerAdapterпри создании новых фрагментов. См. Эту ссылку http://code.google.com/p/openintents/source/browse/trunk/compatibility/AndroidSupportV2/src/android/support/v2/app/FragmentPagerAdapter.java#104

Исмар Сломич
источник
Кстати, в этом разделе вопросов и ответов есть больше информации по этой теме: stackoverflow.com/questions/6976027/…
Thomas
1
что такое входной параметр viewId? Какой вид?
Nilzor
@Nilzor viewId - это идентификатор ViewPager.
Доктор Джеки
Может быть, вместо того, чтобы угадывать тег, фрагмент мог бы сообщить свой тег своей активности onAttach()?
бассейн
4
Это неправильный путь. Ответ @Tony Chan - лучший и правильный способ.
Мортеза Растгу,
17

вам не нужно переопределять instantiateItemили полагаться на совместимость с внутренним makeFragmentNameметодом, вручную создавая теги фрагментов.
instantiateItem- это общедоступный метод, поэтому вы можете и должны вызывать его в onCreateметоде своей деятельности, окруженном вызовами startUpdateи finishUpdateметодами, как описано в PagerAdapter javadoc :

Вызов метода startUpdate (ViewGroup) PagerAdapter указывает, что содержимое ViewPager собирается измениться. За этим последует один или несколько вызовов instantiateItem (ViewGroup, int) и / или destroyItem (ViewGroup, int, Object), а об окончании обновления будет сигнализировать вызов finishUpdate (ViewGroup).

Затем вы можете, используя вышеизложенное, хранить ссылки на экземпляры ваших фрагментов в локальных варах, если вам нужно. См. Пример:

public class MyActivity extends AppCompatActivity {

    Fragment0 tab0; Fragment1 tab1;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.myLayout);
        ViewPager viewPager = (ViewPager) findViewById(R.id.myViewPager);
        MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(adapter);
        ((TabLayout) findViewById(R.id.tabs)).setupWithViewPager(viewPager);

        adapter.startUpdate(viewPager);
        tab0 = (Fragment0) adapter.instantiateItem(viewPager, 0);
        tab1 = (Fragment1) adapter.instantiateItem(viewPager, 1);
        adapter.finishUpdate(viewPager);
    }

    class MyPagerAdapter extends FragmentPagerAdapter {

        public MyPagerAdapter(FragmentManager manager) {super(manager);}

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

        @Override public Fragment getItem(int position) {
            if (position == 0) return new Fragment0();
            if (position == 1) return new Fragment1();
            return null;  // or throw some exception
        }

        @Override public CharSequence getPageTitle(int position) {
            if (position == 0) return getString(R.string.tab0);
            if (position == 1) return getString(R.string.tab1);
            return null;  // or throw some exception
        }
    }
}

instantiateItemсначала попытается получить ссылки на существующие экземпляры фрагментов из FragmentManager. Только если они еще не существуют, он создаст новые, используя getItemметод вашего адаптера, и «сохранит» их FragmentManagerдля будущего использования.

Важно отметить, что даже если вам не нужно получать ссылки на ваши фрагменты, вы все равно должны вызывать instantiateItemвсе свои вкладки, окруженные startUpdate/ finishUpdateв вашем onCreateметоде, например:

    adapter.startUpdate(viewPager);
    // ignoring return values of the below 2 calls, just side effects matter:
    adapter.instantiateItem(viewPager, 0);
    adapter.instantiateItem(viewPager, 1);
    adapter.finishUpdate(viewPager);

Если вы этого не сделаете, вы рискуете, что ваши экземпляры фрагментов никогда не будут привязаны к FragmentManager: когда ваша активность станет переднего плана, instantiateItemбудет автоматически вызываться для получения ваших фрагментов, но startUpdate/ не finishUpdate может (в зависимости от деталей реализации) и что они в основном сделать это начать / зафиксировать . Это может привести к тому, что ссылки на созданные экземпляры фрагментов будут потеряны очень быстро (например, при повороте экрана) и воссозданы гораздо чаще, чем необходимо. В зависимости от того, насколько «тяжелы» ваши фрагменты, это может иметь существенные последствия для производительности. Более того, в таком случае экземпляры фрагментов, хранящиеся в локальных варах, могутFragmentTransaction

становятся устаревшими: если платформа Android пытается получить их FragmentManagerпо какой-либо причине, она потерпит неудачу и, таким образом, будет создавать и использовать новые, в то время как ваши вары по-прежнему будут ссылаться на старые.

Morgwai
источник
1
В некоторых случаях это может быть лучшим решением. Но что произойдет, если FragmentManger убьет фрагмент и заново создаст его?
woltran
1
@woltran FragmentManagerне может просто случайно убить ( уничтожить - правильное слово) ваш Fragment(подумайте, что произойдет, если он решит убить Fragmentотображаемый в данный момент;)). Обычно жизненный цикл a Fragmentпривязан к нему Activity( подробности см. На github.com/xxv/android-lifecycle ) -> a Fragmentможет быть уничтожен, только если он Activityбыл уничтожен. В таком случае , когда пользователь переходит обратно к данному Activityего onCreateбудет называться снова и новый экземпляр Fragmentбудет создан.
morgwai
Это НАСТОЯЩИЙ ответ
MJ Studio
Должны ли вы действительно создавать фрагменты, а не полагаться на их создание, например, когда пользователь прокручивает ViewPager?
Яр
@Yar да, тебе действительно стоит. Отрывок из документации, который я предоставил, четко указывает на это, а в разделе «Дополнительная информация» объясняется, почему.
morgwai
11

Я сделал это так, чтобы определить Hashtable of WeakReferences следующим образом:

protected Hashtable<Integer, WeakReference<Fragment>> fragmentReferences;

Затем я написал метод getItem () следующим образом:

@Override
public Fragment getItem(int position) {

    Fragment fragment;
    switch(position) {
    case 0:
        fragment = new MyFirstFragmentClass();
        break;

    default:
        fragment = new MyOtherFragmentClass();
        break;
    }

    fragmentReferences.put(position, new WeakReference<Fragment>(fragment));

    return fragment;
}

Затем вы можете написать метод:

public Fragment getFragment(int fragmentId) {
    WeakReference<Fragment> ref = fragmentReferences.get(fragmentId);
    return ref == null ? null : ref.get();
}

Кажется, это работает хорошо, и я считаю его менее хакерским, чем

"android:switcher:" + viewId + ":" + position

трюк, поскольку он не зависит от того, как реализован FragmentPagerAdapter. Конечно, если фрагмент был освобожден FragmentPagerAdapter или если он еще не был создан, getFragment вернет null.

Если кто-то обнаружит, что в таком подходе что-то не так, комментарии приветствуются.

человек3000
источник
int fragmentIdследует переименовать вint position
lmaooooo
7
Я использовал очень похожий подход. Но это не удается, когда пейджер создается из пакета savedState. например: Activity переходит в фоновый режим и возвращается на передний план после вызова onSavedStateInstance (). В этом случае методы getItem () не будут вызываться.
Anoop
в чем причина создания вашей собственной карты, если в FragmentManager уже есть одна, которая всегда обновляется? Подробности смотрите в моем ответе.
morgwai
Кроме того, тот факт, что фрагмент был уничтожен, не гарантирует, что на него нет сильных ссылок (хотя это вероятно, но НЕ гарантируется), и в этом случае ваша карта все равно будет содержать устаревшие фрагменты.
morgwai
1
Это не будет работать правильно после того, как система воссоздаст Фрагменты.
EpicPandaForce
10

Я создал этот метод, который позволяет мне получить ссылку на текущий фрагмент.

public static Fragment getCurrentFragment(ViewPager pager, FragmentPagerAdapter adapter) {
    try {
        Method m = adapter.getClass().getSuperclass().getDeclaredMethod("makeFragmentName", int.class, long.class);
        Field f = adapter.getClass().getSuperclass().getDeclaredField("mFragmentManager");
        f.setAccessible(true);
        FragmentManager fm = (FragmentManager) f.get(adapter);
        m.setAccessible(true);
        String tag = null;
        tag = (String) m.invoke(null, pager.getId(), (long) pager.getCurrentItem());
        return fm.findFragmentByTag(tag);
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } 
    return null;
}
Pepijn
источник
Приятно просто вспомнить о создании метода и поля вне метода для повышения производительности
Маркос Васконселос
2

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

Класс ниже обрабатывает такую ​​ситуацию:

public abstract class AbstractHolderFragmentPagerAdapter<F extends Fragment> extends FragmentPagerAdapter {

    public static final String FRAGMENT_SAVE_PREFIX = "holder";
    private final FragmentManager fragmentManager; // we need to store fragment manager ourselves, because parent's field is private and has no getters.

    public AbstractHolderFragmentPagerAdapter(FragmentManager fm) {
        super(fm);
        fragmentManager = fm;
    }

    private SparseArray<WeakReference<F>> holder = new SparseArray<WeakReference<F>>();

    protected void holdFragment(F fragment) {
        holdFragment(holder.size(), fragment);
    }

    protected void holdFragment(int position, F fragment) {
        if (fragment != null)
            holder.put(position, new WeakReference<F>(fragment));
    }

    public F getHoldedItem(int position) {
        WeakReference<F> ref = holder.get(position);
        return ref == null ? null : ref.get();
    }

    public int getHolderCount() {
        return holder.size();
    }

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) { // code inspired by Google's FragmentStatePagerAdapter implementation
        super.restoreState(state, loader);
        Bundle bundle = (Bundle) state;
        for (String key : bundle.keySet()) {
            if (key.startsWith(FRAGMENT_SAVE_PREFIX)) {
                int index = Integer.parseInt(key.substring(FRAGMENT_SAVE_PREFIX.length()));
                Fragment f = fragmentManager.getFragment(bundle, key);
                holdFragment(index, (F) f);
            }
        }
    }

    @Override
    public Parcelable saveState() {
        Bundle state = (Bundle) super.saveState();
        if (state == null)
            state = new Bundle();

        for (int i = 0; i < holder.size(); i++) {
            int id = holder.keyAt(i);
            final F f = getHoldedItem(i);
            String key = FRAGMENT_SAVE_PREFIX + id;
            fragmentManager.putFragment(state, key, f);
        }
        return state;
    }
}
нетимен
источник
1

Основная проблема, связанная с получением дескриптора фрагментов, заключается в том, что вы не можете полагаться на getItem (). После изменения ориентации ссылки на фрагменты будут нулевыми, и getItem () больше не вызывается.

Вот подход, который не зависит от реализации FragmentPagerAdapter для получения тега. Переопределите instantiateItem (), который вернет фрагмент, созданный из getItem () или найденный из диспетчера фрагментов.

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Object value =  super.instantiateItem(container, position);

    if (position == 0) {
        someFragment = (SomeFragment) value;
    } else if (position == 1) {
        anotherFragment = (AnotherFragment) value;
    }

    return value;
}
Адам
источник
0

См. Этот пост о возврате фрагментов из FragmentPagerAdapter. Полагается на то, что вы знаете индекс вашего фрагмента, но это будет установлено в getItem () (только при создании экземпляра)

Сообщество
источник
0

Мне удалось решить эту проблему, используя идентификаторы вместо тегов. (Я использую я определил FragmentStatePagerAdapter, который использует мои пользовательские фрагменты, в которых я переопределил метод onAttach, где вы где-то сохраняете идентификатор:

@Override
public void onAttach(Context context){
    super.onAttach(context);
    MainActivity.fragId = getId();
}

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

Fragment f = getSupportFragmentManager.findFragmentById(fragId);
user2740905
источник
0

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

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

Во фрагменте:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        mListener = (OnListInteractionListener) activity;
        mListener.setListFrag(this);
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnFragmentInteractionListener");
    }
}

Затем в действии:

@Override
public void setListFrag(MyListFragment lf) {
    if (mListFragment == null) {
        mListFragment = lf;
    }
}

И, наконец, в действии onCreate ():

if (savedInstanceState != null) {
    if (mListFragment != null)
        mListFragment.setListItems(items);
}

При таком подходе к действию прикрепляется фактический видимый фрагмент, не создавая новый.

TacoEater
источник
0

Не уверен, что мой метод был правильным или лучшим способом сделать это, поскольку я относительно новичок в Java / Android, но он действительно работал (я уверен, что он нарушает объектно-ориентированные принципы, но никакое другое решение не сработало для моего варианта использования).

У меня был хостинг Activity, который использовал ViewPager с FragmentStatePagerAdapter. Чтобы получить ссылки на фрагменты, созданные FragmentStatePagerAdapter, я создал интерфейс обратного вызова внутри класса фрагмента:

public interface Callbacks {
    public void addFragment (Fragment fragment);
    public void removeFragment (Fragment fragment);
}

В процессе хостинга я реализовал интерфейс и создал LinkedHasSet для отслеживания фрагментов:

public class HostingActivity extends AppCompatActivity implements ViewPagerFragment.Callbacks {

    private LinkedHashSet<Fragment> mFragments = new LinkedHashSet<>();

    @Override
    public void addFragment (Fragment fragment) {
        mFragments.add(fragment);
    }

    @Override
    public void removeFragment (Fragment fragment) {
        mFragments.remove(fragment);
    }
}

В классе ViewPagerFragment я добавил фрагменты в список внутри onAttach и удалил их внутри onDetach:

public class ViewPagerFragment extends Fragment {

    private Callbacks mCallbacks;

    public interface Callbacks {
        public void addFragment (Fragment fragment);
        public void removeFragment (Fragment fragment);
    } 

    @Override
    public void onAttach (Context context) {
        super.onAttach(context);
        mCallbacks = (Callbacks) context;
        // Add this fragment to the HashSet in the hosting activity
        mCallbacks.addFragment(this);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        // Remove this fragment from the HashSet in the hosting activity
        mCallbacks.removeFragment(this);
        mCallbacks = null;
    }
}

Теперь в рамках деятельности по размещению вы сможете использовать mFragments для итерации по фрагментам, которые в настоящее время существуют в FragmentStatePagerAdapter.

sbearben
источник
0

Этот класс делает свое дело, не полагаясь на внутренние теги. Предупреждение. Доступ к фрагментам следует осуществлять с помощью метода getFragment, а не метода getItem.

public class ViewPagerAdapter extends FragmentPagerAdapter {

    private final Map<Integer, Reference<Fragment>> fragments = new HashMap<>();
    private final List<Callable0<Fragment>> initializers = new ArrayList<>();
    private final List<String> titles = new ArrayList<>();

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

    void addFragment(Callable0<Fragment> initializer, String title) {
        initializers.add(initializer);
        titles.add(title);
    }

    public Optional<Fragment> getFragment(int position) {
        return Optional.ofNullable(fragments.get(position).get());
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment =  initializers.get(position).execute();
        return fragment;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        fragments.put(position, new WeakReference<>(fragment));
        return fragment;
    }

    @Override
    public int getCount() {
        return initializers.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles.get(position);
    }
}
Алекс Мирагалл
источник
-5

Просто попробуйте этот код,

public class MYFragmentPAdp extends FragmentPagerAdapter {

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

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

     @Override
     public Fragment getItem(int position) {
         if (position == 0)
             Fragment fragment = new Fragment1();
         else (position == 1)
             Fragment fragment = new Fragment2();
         return fragment;
     }
}
Наджиб Ахмед Путхавала
источник
Наджиб, как я объяснил в своем ответе ниже, getItem () создает новый фрагмент вместо возврата существующих, поскольку можно было ожидать, что данное имя получит а не создаст . См. Мое решение в том же посте.
Ismar Slomic
Фрагмент фрагмента = новый YourCustomFragmentClass (); напишите сюда проверьте на это.
Наджиб Ахмед Путхавала
Я до сих пор не понимаю, как это меняет тот факт, что вы создаете новый фрагмент вместо того, чтобы получить существующий ..
Исмар Сломик
Вы по-прежнему инициализируете и возвращаете только свой собственный фрагмент, например, Fragment fragment = new YourFragment (); вернуть фрагмент;
Наджиб Ахмед Путхавала