FragmentPagerAdapter getItem non viene chiamato


123

Non sono in grado di riutilizzare il frammento in FragmentPagerAdapter .. Utilizzando il metodo destroyItem (), sta eliminando il frammento ma ancora non viene chiamato nuovamente getItem () .. Ci sono solo 2-3 immagini, quindi sto usando FragmentPagerAdapter invece di 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;
    }
}

E in FragmentActivity,

pager.setAdapter(new ExamplePagerAdapter(getSupportFragmentManager(), res2)); 

3
C'è un motivo particolare per cui hai ignorato destroyItem()? Non è necessario.
CommonsWare,

per inizializzare di nuovo usa FragmentStatePagerAdapter anche chiamare quando lo sovrascrivi super.destroyItem (container, position, object);
faiziii

Risposte:


306

BACIO Risposta:

Uso semplice FragmentStatePagerAdapter invece di FragmentPagerAdapter .

Ho avuto la risposta .. In primo luogo ho pensato di eliminare questa domanda perché sto facendo un errore molto stupido, ma questa risposta aiuterà qualcuno che sta affrontando lo stesso problema che invece di FragmentPagerAdapter, usa FragmentStatePagerAdapter.

Come @BlackHatSamurai ha menzionato nel commento:

Il motivo per cui funziona è perché FragmentStatePagerAdapterdistrugge come frammenti che non vengono utilizzati. FragmentPagerAdapternon.


Grazie mille La nostra risposta mi ha aiutato molto.
Priya

1
Odio essere un altro "anch'io!" post, ma sì>. <Grazie per non aver eliminato la domanda.
Paul Ruiz

34
Il motivo per cui funziona è perché FragmentStatePagerAdapter distrugge come frammenti che non vengono utilizzati. FragmentPagerAdapter no.
BlackHatSamurai

3
Solo per riferimento futuro per coloro che potrebbero trovarlo durante la ricerca di un problema specifico che stanno avendo; leggere sia su FragmentPagerAdapter che su FragmentStatePagerAdapter. Si comportano in modo diverso per un motivo e il tuo uso specifico potrebbe richiedere uno rispetto all'altro.
Chris Stewart

2
@najibputhawala Ho usato FragmentStatePagerAdapter ma devo ancora affrontare lo stesso problema. getItem () non chiamato
sam_k

168

L'utilizzo di a FragmentStatePagerAdapternon ha risolto completamente il mio problema che era un problema simile in cui onCreateViewnon veniva chiamato per i frammenti figlio nel cercapersone della vista. In realtà sto annidando il mio FragmentPagerAdapterinterno di un altro,Fragment quindi è FragmentManagerstato condiviso in tutti loro e quindi conservando le istanze dei vecchi frammenti. La correzione consisteva nel fornire un'istanza di getChildFragmentManageral costruttore del FragmentPagerAdapterframmento nel mio host. Qualcosa di simile a...

FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());

Il getChildFragmentManager()metodo è accessibile tramite un frammento e questo ha funzionato per me perché restituisce un privato FragmentManagerper quel frammento specificamente per le situazioni in cui è necessario annidare i frammenti. Spero che questo aiuti qualcuno che potrebbe avere lo stesso problema che avevo io !!

  • Tieni presente, tuttavia, che per utilizzare la getChildFragmentManager()tua versione minima dell'API deve essere almeno 17 (4.2), quindi questo potrebbe farti impazzire. Ovviamente, se stai usando frammenti dalla libreria di supporto v4 dovresti stare bene.

25
Questa è la risposta corretta. Il problema è dovuto al fatto che i frammenti annidati in altri frammenti dovrebbero usare getChildrenFragmentManager () invece di getFragmentManager ().
shihpeng

Grazie mille, mi ci è voluta un'eternità per trovare questa risposta!
Shpongoloid

Sono d'accordo con @shihpeng. Questa dovrebbe essere la risposta corretta.
Raymond Lukanta

Questa è stata una soluzione per me. Grazie mille per aver inviato una risposta
user3734429

I documenti dovrebbero davvero chiamarlo fuori nel walk-thru. È molto realistico che un ViewPager venga caricato all'interno di un frammento. Grazie per aver pubblicato questa risposta.
lavorato l'

7

Oltrepassare long getItemId (int position)

FragmentPagerAdaptermemorizza nella cache i frammenti che crea utilizzando getItem. Stavo affrontando lo stesso problema, anche dopo che la chiamata notifyDataSetChanged() getItemnon veniva chiamata.

Questa è in realtà una funzionalità e non un bug. È necessario eseguire l'override in getItemIdmodo da poter riutilizzare correttamente i frammenti. Dato che stai rimuovendo frammenti, le tue posizioni stanno cambiando. Come accennato nei documenti:

long getItemId (int position)

Restituisce un identificatore univoco per l'articolo nella posizione specificata.

L'implementazione predefinita restituisce la posizione data. Le sottoclassi dovrebbero sovrascrivere questo metodo se le posizioni degli elementi possono cambiare.

Fornisci semplicemente un ID univoco a ogni frammento e il gioco è fatto.

Usando una FragementStatePagerAdaptero tornare POSITION_NONEin int getItemPosition (Object object)è sbagliato. Non otterrai alcuna memorizzazione nella cache.


Questa era la risposta corretta. Ho dovuto fornire ID diversi per i frammenti in getItemIdAND aggiustare getItemPositionper restituire POSITION_NONESE il frammento doveva essere rimosso. Ho una bandiera enum per questo. Dopodiché getItemverrà chiamato.
Murat Karagöz

Grazie @ MuratKaragöz per il +50 :)
vedant il

5

Ho fatto quello che avevano pubblicato @kanika e @ Jraco11 ma avevo ancora il problema.

Quindi, dopo molte modifiche, ne ho trovato uno che funzionava per me ed è stato aggiunto al mio FragmentPagerAdapter il codice successivo:

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

Secondo quanto ho letto, getItemPosition viene utilizzato per notificare al ViewPager se aggiornare o meno un elemento e per evitare aggiornamenti se gli elementi nelle posizioni visibili non sono cambiati.


2

Ci sono due diversi scenari: 1.) Hai lo stesso layout per ogni cercapersone: in tal caso, sarà meglio se estenderai l'adattatore personalizzato tramite PagerAdapter e restituirai un unico layout.

2.) Hai un layout diverso per ogni cercapersone: in tal caso, sarà meglio estendere il tuo adattatore personalizzato tramite FragmentStatePagerAdapter e restituire diversi frammenti per ogni cercapersone.


2

il metodo getItem()è utilizzato solo per creare nuovi elementi. Una volta creato, questo metodo non verrà chiamato. Se è necessario ottenere un articolo che è la valuta utilizzata dall'adattatore, utilizzare questo metodo:

pagerAdapter.instantiateItem(viewPager, TAB_POS)

0

Ho scoperto che l'impostazione di un listener sul layout della scheda ha impedito che fosse chiamato, probabilmente perché hanno solo spazio per un ascoltatore tabLayout.setOnTabSelectedListenerinvece di un array di listener.

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.