Come ottenere frammenti esistenti quando si usa FragmentPagerAdapter


99

Ho problemi a far comunicare tra loro i miei frammenti attraverso il Activity, che utilizza il FragmentPagerAdapter, come una classe di supporto che implementa la gestione delle schede e tutti i dettagli di connessione a ViewPagercon associati TabHost. L'ho implementato FragmentPagerAdapterproprio come fornito dal progetto di esempio Android Support4Demos .

La domanda principale è come posso ottenere un particolare frammento da FragmentManagerquando non ho né Id né Tag? FragmentPagerAdaptersta creando i frammenti e generando automaticamente l'ID e i tag.



@ jk2K come può essere un duplicato di una domanda che è stata posta 1 anno dopo
Davi,

@Dawit duplicato come un'etichetta, non correlato al tempo, le domande successive hanno visualizzazioni più alte
jk2K

La maggior parte delle risposte qui non funzionano in produzione, in modo da controllare la mia risposta in stackoverflow.com/a/54280113/2413303
EpicPandaForce

Risposte:


194

Riepilogo del problema

Nota: in questa risposta farò riferimento FragmentPagerAdaptere il suo codice sorgente. Ma la soluzione generale dovrebbe applicarsi anche a FragmentStatePagerAdapter.

Se stai leggendo questo, probabilmente sai già che FragmentPagerAdapter/ FragmentStatePagerAdapterè pensato per creare Fragmentsper te ViewPager, ma durante la ricreazione dell'attività (sia da una rotazione del dispositivo o dal sistema che uccide la tua app per riguadagnare memoria) questi Fragmentsnon verranno creati di nuovo, ma invece il loro istanze recuperate daFragmentManager . Ora dì che hai Activitybisogno di ottenere un riferimento a questi Fragmentsper lavorare su di loro. Non hai creato un ido tagper questi Fragmentsperché FragmentPagerAdapter impostali internamente . Quindi il problema è come ottenere un riferimento a loro senza queste informazioni ...

Problema con le soluzioni attuali: affidarsi al codice interno

Molte delle soluzioni che ho visto su questo e simili domande si basano su come ottenere un riferimento al esistente Fragmentchiamando FragmentManager.findFragmentByTag()e imitando il tag creato internamente:"android:switcher:" + viewId + ":" + id . Il problema con questo è che ti affidi al codice sorgente interno, che come tutti sappiamo non è garantito che rimanga lo stesso per sempre. Gli ingegneri Android di Google potrebbero facilmente decidere di modificare la tagstruttura che romperebbe il codice lasciandoti incapace di trovare un riferimento all'esistente Fragments.

Soluzione alternativa senza fare affidamento sull'interno tag

Ecco un semplice esempio di come ottenere un riferimento al Fragmentsrestituito da FragmentPagerAdapterche non si basa sull'insieme interno tagssu Fragments. La chiave è sovrascrivere instantiateItem()e salvare i riferimenti lì invece che in 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();
        }
    }
}

o se preferisci lavorare con tagsvariabili / riferimenti al membro della classe invece Fragmentsche puoi anche prendere l' tagsinsieme da FragmentPagerAdapternello stesso modo: NOTA: questo non si applica a FragmentStatePagerAdapterpoiché non si imposta tagsdurante la creazione del suo 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;
}

Si noti che questo metodo NON si basa sull'imitazione tagdell'insieme interno di FragmentPagerAdaptere utilizza invece API appropriate per il recupero. In questo modo anche se le tagmodifiche nelle future versioni di SupportLibrarysarai comunque al sicuro.


Non dimenticare che, a seconda del design del tuo Activity, quello su Fragmentscui stai cercando di lavorare può o non può ancora esistere, quindi devi tenerne conto facendo nullcontrolli prima di utilizzare i tuoi riferimenti.

Inoltre, se invece stai lavorando con FragmentStatePagerAdapter, allora non vuoi mantenere riferimenti rigidi al tuo Fragmentsperché potresti averne molti e riferimenti rigidi li terrebbero inutilmente in memoria. Salvare invece i Fragmentriferimenti in WeakReferencevariabili anziché in quelli standard. Come questo:

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
Questa è davvero una buona soluzione, ma sembra perdere la sua efficacia se non sai quanti frammenti verranno passati.
Riot Goes Woof

3
@Zorpix puoi memorizzare i frammenti di creazione in una HashMap: map.put (position, createdFragment);
Tom Bevelander

12
Questo merita il segno di spunta! Modo molto intelligente e completo per ottenere questo risultato. Mi hai aiutato molto grazie!
young_souvlaki

2
All'inizio questa soluzione sembrava troppo complicata, quindi l'ho saltata. Alla fine ci sono tornato, però, perché le altre risposte non erano soddisfacenti. E non è stato così difficile come pensavo.
Suragch

1
non c'è bisogno di sovrascrivere nulla e in realtà non dovresti sovrascriverlo instantiateItem. il modo corretto di farlo è quello di chiamare instantiateItem in onCreatemodo di vostra attività circondato da startUpdatee finishUpdate. Vedi la mia risposta per i dettagli
morgwai

82

Ho trovato la risposta alla mia domanda basata sul seguente post: riutilizzo di frammenti in un fragmentpageradapter

Poche cose ho imparato:

  1. getItem(int position)nel FragmentPagerAdapternome piuttosto fuorviante di ciò che questo metodo fa effettivamente. Crea nuovi frammenti, non restituendo quelli esistenti. In questo senso, il metodo dovrebbe essere rinominato in qualcosa di simile createItem(int position)in Android SDK. Quindi questo metodo non ci aiuta a ottenere frammenti.
  2. In base alla spiegazione nel post di supporto FragmentPagerAdapter contiene riferimenti a vecchi frammenti , dovresti lasciare la creazione dei frammenti a FragmentPagerAdaptere, quindi, non hai alcun riferimento ai frammenti o ai loro tag. Se hai un tag fragment, puoi facilmente recuperare il riferimento ad esso dal file FragmentManagerchiamando findFragmentByTag(). Abbiamo bisogno di un modo per scoprire il tag di un frammento in una data posizione della pagina.

Soluzione

Aggiungi il seguente metodo di supporto nella tua classe per recuperare il tag di frammento e inviarlo al findFragmentByTag()metodo.

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

NOTA! Questo è il metodo identico FragmentPagerAdapterutilizzato durante la creazione di nuovi frammenti. Vedi questo link http://code.google.com/p/openintents/source/browse/trunk/compatibility/AndroidSupportV2/src/android/support/v2/app/FragmentPagerAdapter.java#104


A proposito, c'è di più sull'argomento in questa domanda e risposta
Thomas,

1
qual è il parametro di input viewId? Quale vista?
Nilzor

@Nilzor viewId è l'id del ViewPager.
Dr.jacky

Forse invece di indovinare il tag, il frammento potrebbe indicare il suo tag alla sua attività in onAttach()?
bacino

4
Questo non è il modo giusto. La risposta di @Tony Chan è il modo migliore e corretto.
Morteza Rastgoo

17

non è necessario sovrascrivere instantiateItemné fare affidamento sulla compatibilità con il makeFragmentNamemetodo interno creando manualmente tag di frammento.
instantiateItemè un metodo pubblico , quindi puoi e in realtà dovresti chiamarlo nel onCreatemetodo della tua attività circondato da chiamate a startUpdatee finishUpdatemetodi come descritto in PagerAdapter javadoc :

Una chiamata al metodo PagerAdapter startUpdate (ViewGroup) indica che il contenuto di ViewPager sta per cambiare. Seguiranno una o più chiamate a instantiateItem (ViewGroup, int) e / o destroyItem (ViewGroup, int, Object) e la fine di un aggiornamento verrà segnalata da una chiamata a finishUpdate (ViewGroup).

Puoi quindi, in base a quanto sopra, memorizzare i riferimenti alle istanze dei tuoi frammenti su vars locali, se necessario. Vedi esempio:

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

instantiateItemproverà prima a ottenere riferimenti a istanze di frammento esistenti da FragmentManager. Solo se non esistono ancora, ne creerà di nuovi usando il getItemmetodo del tuo adattatore e li "memorizzerà" FragmentManagerper un uso futuro.

È importante notare che anche se non hai bisogno di ottenere riferimenti ai tuoi frammenti, dovresti comunque chiamare instantiateItemtutte le tue schede circondate da startUpdate/ finishUpdatenel tuo onCreatemetodo in questo modo:

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

Se non si fa così, allora si sta rischiando che le istanze di frammenti non saranno mai impegnati a FragmentManager: quando l'attività diventa di primo piano instantiateItemsarà chiamato automaticamente per ottenere i vostri frammenti, ma startUpdate/ finishUpdate potrebbe non (a seconda di dettagli di implementazione) e quello che in fondo fare è iniziare / eseguire il commit di un file FragmentTransaction.
Ciò può comportare la perdita molto rapida dei riferimenti alle istanze di frammento create (ad esempio quando si ruota lo schermo) e ricreati molto più spesso del necessario. A seconda di quanto "pesanti" sono i tuoi frammenti, potrebbe avere conseguenze sulle prestazioni non trascurabili.
Inoltre, in tal caso le istanze di frammenti memorizzati su vars locali possonodiventare obsoleto: se la piattaforma Android tenta di ottenerli da FragmentManagerper qualsiasi motivo, fallirà e quindi ne creerà e utilizzerà di nuovi, mentre i tuoi vars faranno ancora riferimento a quelli vecchi.


1
Potrebbe essere la soluzione migliore in alcuni casi. Ma cosa succederà se FragmentManger ucciderà il frammento e lo riclassificherà?
woltran

1
@woltran FragmentManagernon può semplicemente uccidere casualmente ( distruggere è la parola giusta qui) il tuo Fragment(pensa a cosa accadrebbe se decidesse di uccidere un Fragmentche è attualmente visualizzato;)). Generalmente il ciclo di vita di a Fragmentè vincolato al suo Activity(vedi github.com/xxv/android-lifecycle per i dettagli) -> a Fragmentpuò essere distrutto solo se è Activitystato distrutto. In tal caso, quando un utente si sposta indietro al dato Activitysua onCreatesarà chiamato di nuovo e una nuova istanza del Fragmentverrà creato.
morgwai

Questa è la risposta REALE
MJ Studio

Dovresti davvero creare frammenti piuttosto che fare affidamento sul fatto che vengano creati mentre un utente scorre ViewPager, ad esempio?
Yar

@Yar sì, dovresti davvero. L'estratto della documentazione che ho fornito lo afferma chiaramente e la sezione "Alcune informazioni aggiuntive" spiega perché.
morgwai

11

Il modo in cui l'ho fatto è definire un Hashtable di WeakReferences come segue:

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

Quindi ho scritto il metodo getItem () in questo modo:

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

Quindi puoi scrivere un metodo:

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

Questo sembra funzionare bene e lo trovo un po 'meno complicato del

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

trucco, poiché non si basa su come viene implementato il FragmentPagerAdapter. Ovviamente se il frammento è stato rilasciato da FragmentPagerAdapter o se non è stato ancora creato, getFragment restituirà null.

Se qualcuno trova qualcosa di sbagliato in questo approccio, i commenti sono più che benvenuti.


int fragmentIddovrebbe essere rinominatoint position
lmaooooo

7
Stavo usando un approccio molto simile. Ma questo fallisce quando il cercapersone viene creato da un bundle savedState. ad esempio: l'attività passa in background e torna in primo piano dopo la chiamata di onSavedStateInstance (). In tal caso i metodi getItem () non verranno chiamati.
Anoop

qual è il motivo per creare la tua mappa visto che ce n'è già una in FragmentManager che è sempre aggiornata? Vedi la mia risposta per i dettagli.
morgwai

inoltre, il fatto che un frammento sia stato distrutto non garantisce che non vi siano riferimenti forti ad esso (sebbene sia probabile, ma NON garantito), nel qual caso la tua mappa conterrebbe ancora frammenti obsoleti.
morgwai

1
Ciò non funzionerà correttamente dopo che il sistema ha ricreato i frammenti.
EpicPandaForce

10

Ho creato questo metodo che funziona per me per ottenere un riferimento al frammento corrente.

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

Bello solo ricordare di aver creato il metodo e il campo fuori dal metodo per una migliore prestazione
Marcos Vasconcelos

2

la soluzione suggerita da @ personne3000 è carina, ma ha un problema: quando l'attività va in background e viene uccisa dal sistema (per ottenere un po 'di memoria libera) e poi ripristinata, fragmentReferencessarà vuoto, perché getItemnon lo sarebbe chiamato.

La classe seguente gestisce tale situazione:

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

Il blocco stradale principale per ottenere un controllo sui frammenti è che non puoi fare affidamento su getItem (). Dopo una modifica dell'orientamento, i riferimenti ai frammenti saranno nulli e getItem () non verrà chiamato di nuovo.

Ecco un approccio che non si basa sull'implementazione di FragmentPagerAdapter per ottenere il tag. Sostituisci instantiateItem () che restituirà il frammento creato da getItem () o trovato dal fragment manager.

@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

Vedi questo post sulla restituzione di frammenti da FragmentPagerAdapter. Si basa sul fatto che tu conosca l'indice del tuo frammento, ma questo sarebbe impostato in getItem () (solo all'istanza)


0

Sono riuscito a risolvere questo problema utilizzando gli ID invece dei tag. (Sto usando ho definito FragmentStatePagerAdapter che usa i miei frammenti personalizzati in cui ho sovrascritto il metodo onAttach, dove salvi l'id da qualche parte:

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

E poi accedi facilmente al frammento all'interno dell'attività:

Fragment f = getSupportFragmentManager.findFragmentById(fragId);

0

Non so se questo sia l'approccio migliore, ma nient'altro ha funzionato per me. Tutte le altre opzioni, incluso getActiveFragment, hanno restituito null o hanno causato l'arresto anomalo dell'app.

Ho notato che durante la rotazione dello schermo il frammento veniva attaccato, quindi l'ho usato per rimandare il frammento all'attività.

Nel frammento:

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

Quindi nell'attività:

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

E infine in attività onCreate ():

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

Questo approccio associa il frammento visibile effettivo all'attività senza crearne uno nuovo.


0

Non sono sicuro che il mio metodo fosse il modo corretto o migliore per farlo poiché sono un principiante relativo con Java / Android, ma ha funzionato (sono sicuro che viola i principi orientati agli oggetti ma nessun'altra soluzione ha funzionato per il mio caso d'uso).

Avevo un'attività di hosting che utilizzava un ViewPager con un FragmentStatePagerAdapter. Per ottenere riferimenti ai frammenti creati da FragmentStatePagerAdapter ho creato un'interfaccia di callback all'interno della classe fragment:

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

Nell'attività di hosting ho implementato l'interfaccia e creato un LinkedHasSet per tenere traccia dei frammenti:

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

All'interno della classe ViewPagerFragment ho aggiunto i frammenti all'elenco all'interno di onAttach e li ho rimossi all'interno di 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;
    }
}

All'interno dell'attività di hosting sarai ora in grado di utilizzare mFragments per scorrere i frammenti attualmente esistenti in FragmentStatePagerAdapter.


0

Questa classe fa il trucco senza fare affidamento su tag interni. Avvertenza: è necessario accedere ai frammenti utilizzando il metodo getFragment e non quello 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

Continua a provare questo codice,

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, come ho spiegato nella mia risposta sotto getItem (), sta creando un nuovo frammento invece di restituire quelli esistenti come ci si potrebbe aspettare che un dato nome ottenga e non crei . Vedi la mia soluzione nello stesso post.
Ismar Slomic

Fragment fragment = new YourCustomFragmentClass (); scrivi qui controlla per questo.
Najib Ahmed Puthawala

Ancora non capisco come questo cambi il fatto che stai creando un nuovo frammento invece di ottenerne uno esistente ..
Ismar Slomic

Devi ancora inizializzare e tornare solo per il tuo frammento personalizzato, come Fragment fragment = new YourFragment (); frammento di ritorno;
Najib Ahmed Puthawala
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.