Як отримати наявні фрагменти при використанні FragmentPagerAdapter


99

У мене проблеми з тим, щоб мої фрагменти спілкувалися один з одним через Activity, який використовується FragmentPagerAdapter, як клас помічника, який реалізує управління вкладками та всі деталі з'єднання ViewPagerз асоційованими TabHost. Я реалізував FragmentPagerAdapterтак само, як це передбачено зразком проекту Android4 Support4Demos .

Головне питання - як я можу отримати конкретний фрагмент, FragmentManagerколи у мене немає ні Id, ні тегу? FragmentPagerAdapterстворює фрагменти та автоматично генерує id та теги.



@ jk2K Як це може бути дублікат запитання, яке було задано через 1 рік після
Деві

@Dawit дублікат, як етикетка, не пов’язаний із часом, пізніші питання мають вищий перегляд
jk2K

Більшість відповідей тут не працюють у виробництві, так що перевірити мою відповідь в stackoverflow.com/a/54280113/2413303
EpicPandaForce

Відповіді:


194

Короткий зміст проблеми

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

Якщо ви читаєте це, ви, напевно, вже знаєте, що FragmentPagerAdapter/ FragmentStatePagerAdapterпризначено створити Fragmentsдля себе ViewPager, але після відтворення активності (чи від обертання пристрою чи від системи, що вбиває ваш додаток, щоб відновити пам'ять), вони 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 (позиція, створенийFragment);
Том Бевеландер

12
Цього заслуговує галочка! Дуже розумний і всебічний спосіб досягти цього. Ви мені дуже допомогли, дякую!
young_souvlaki

2
Спочатку це рішення виглядало занадто складно, тому я пропустив його. Я, нарешті, повернувся до цього, хоча інші відповіді були незадовільними. І це було не так важко, як я думав.
Сурагч

1
не потрібно нічого переосмислювати, і ви насправді не повинні переважати instantiateItem. правильний спосіб зробити це - зателефонувати instantiateItem у onCreateспосіб вашої діяльності в оточенні startUpdateта finishUpdate. Дивіться мою відповідь для деталей
morgwai

82

Я знайшов відповідь на своє запитання на основі наступного допису: повторне використання фрагментів у fragmentpageradapter

Мало чого я навчився:

  1. getItem(int position)у FragmentPagerAdapterдосить хибній назві того, що насправді робить цей метод. Він створює нові фрагменти, не повертаючи існуючих. Таким чином, метод слід перейменувати на щось подібне createItem(int position)до Android SDK. Тож цей метод не допомагає нам отримати фрагменти.
  2. Виходячи з пояснень у поштовій підтримці FragmentPagerAdapterholds, що посилаються на старі фрагменти, ви повинні залишити створення фрагментів на 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/…
Томас

1
що таке вхідний параметр viewId? Який погляд?
Nilzor

@Nilzor viewId - ідентифікатор ViewPager.
Dr.jacky

Може замість того, щоб вгадати тег, фрагмент міг би вказати його тегу на його активність у onAttach()?
басейн

4
Це не правильний шлях. @Tony Chan відповідь - найкращий і правильний спосіб.
Morteza Rastgoo

16

вам не потрібно переосмислювати instantiateItemта не покладатися на сумісність із внутрішнім makeFragmentNameметодом, вручну створюючи фрагменти тегів.
instantiateItemце загальнодоступний метод, тому ви можете і насправді слід називати його onCreateметодом своєї діяльності, оточеним дзвінками startUpdateта finishUpdateметодами, як описано в PagerAdapter javadoc :

Заклик до методу startUpdate методу PagerAdapter (ViewGroup) вказує на те, що вміст ViewPager збирається змінити. Наступний один або більше викликів до instantiateItem (ViewGroup, int) та / або знищитиItem (ViewGroup, int, Object), а кінець оновлення буде сигналізований за допомогою виклику для завершення оновлення (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 може НЕ ( в залежності від деталей реалізації) і то , що вони в основному робити - починати / вчиняти a FragmentTransaction.
Це може призвести до того, що посилання на створені фрагменти екземплярів втрачаються дуже швидко (наприклад, при повороті екрана) і відтворюються набагато частіше, ніж потрібно. Залежно від того, наскільки «важкі» ваші фрагменти, це може мати несуттєві наслідки для продуктивності.
Крім того, в такому випадку екземпляри фрагментів зберігаються на локальному Варса можестати несвіжими: якщо платформа Android буде намагатися отримати їх з FragmentManagerбудь-якої причини, вона вийде з ладу і, таким чином, створить і використовувати нові, тоді як ваші користувачі все ще посилаються на старі.


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, наприклад?
Яр

@ Так, ви справді повинні. Документ, який я надав, чітко визначає це, і розділ "Деякі додаткові відомості" пояснює, чому.
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 повернеться в нуль.

Якщо хтось виявить щось не так у цьому підході, коментарі більш ніж вітаються.


int fragmentIdмає бути перейменовано наint position
lmaooooo

7
Я використовував дуже подібний підхід. Але це не вдається, коли пейджер створений із пакета збережених держав. наприклад: Діяльність переходить на другий план і повертається на перший план після виклику 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;
}

Приємно просто пам’ятати про створення методу та поля поза методом для кращої продуктивності
Маркос Васкончелос

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

0

Я не знаю, чи це найкращий підхід, але нічого іншого для мене не вийшло. Усі інші параметри, включаючи getActiveFragment, повернули нуль або спричинили збій програми.

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

У фрагменті:

@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);
}

Цей підхід приєднує фактичний видимий фрагмент до діяльності, не створюючи нового.


0

Не впевнений, чи мій метод був правильним чи найкращим способом зробити це, оскільки я відносний початківець з Java / Android, але він спрацював (я впевнений, що він порушує об'єктно-орієнтовані принципи, але жодне інше рішення не працювало для мого випадку використання).

У мене була діяльність хостингу, яка використовувала 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;
    }
}

У ході хостингової діяльності ви тепер зможете використовувати mFragment для повторення фрагментів, що існують у FragmentStatePagerAdapter.


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;
     }
}

Najib, як я пояснив у своїй відповіді нижче, getItem () створює новий фрагмент замість повернення існуючих, як можна було очікувати, що дане ім'я отримати, а не створити . Дивіться моє рішення в тому самому дописі.
Ісмар Сломіч

Фрагмент фрагмента = новий YourCustomFragmentClass (); пишіть тут перевірити це.
Наджіб Ахмед Путхавала

Я все ще не розумію, як це змінить той факт, що ви створюєте новий фрагмент замість того, щоб отримати існуючий ..
Ісмар Сломіч

Ви все ще ініціалізуєте та повертаєте лише для свого власного фрагмента, наприклад, фрагмент Fragment = new YourFragment (); повернутий фрагмент;
Наджіб Ахмед Путхавала
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.