Qual è la differenza tra FragmentPagerAdapter e FragmentStatePagerAdapter?


375

Qual è la differenza tra FragmentPagerAdaptere FragmentStatePagerAdapter?

Informazioni FragmentPagerAdaptersulla guida di Google dice:

Questa versione del cercapersone è la migliore da usare quando ci sono una manciata di frammenti tipicamente più statici da sfogliare, come una serie di schede. Il frammento di ogni pagina visitata dall'utente verrà conservato in memoria, sebbene la sua gerarchia di visualizzazione possa essere distrutta quando non visibile. Ciò può comportare l'utilizzo di una quantità significativa di memoria poiché le istanze di frammento possono trattenere una quantità arbitraria di stato. Per gruppi di pagine più grandi, considerare FragmentStatePagerAdapter.

E su FragmentStatePagerAdapter:

Questa versione del cercapersone è più utile in presenza di un numero elevato di pagine, funzionando più come una visualizzazione elenco. Quando le pagine non sono visibili all'utente, il loro intero frammento può essere distrutto, mantenendo solo lo stato salvato di quel frammento. Ciò consente al cercapersone di conservare molta meno memoria associata a ciascuna pagina visitata rispetto FragmentPagerAdapteral costo di un potenziale maggior sovraccarico quando si passa da una pagina all'altra .

Quindi ho solo 3 frammenti. Ma tutti sono moduli separati con una grande quantità di dati.

Fragment1gestisce alcuni dati (che gli utenti inseriscono) e li passa attraverso l'attività Fragment2, che è semplicemente un semplice ListFragment. Fragment3è anche a ListFragment.

Quindi le mie domande sono : quale adattatore dovrei usare? FragmentPagerAdaptero FragmentStatePagerAdapter?


2
Penso che avere solo 3 frammenti ti qualifichi per usare FragmentPagerAdapter. Le schede per questi frammenti saranno probabilmente tutte visibili contemporaneamente.
IgorGanapolsky,

2
questo post mi ha risparmiato 5-6 ore perché utilizzo un tipo errato di adattatore
Nantaphop,

1
Risposta a questa domanda getta ancora una domanda stackoverflow.com/questions/9156406/...
Piyush Kukadiya

c'è FragmentPagerAdaptere FragmentStatePagerAdapterma cos'è FragmentStateAdapter?
the_prole

Risposte:


292

Come dicono i documenti, pensaci in questo modo. Se dovessi fare un'applicazione come un lettore di libri, non vorrai caricare tutti i frammenti in memoria contemporaneamente. Vorresti caricare e distruggere Fragmentsmentre l'utente legge. In questo caso utilizzerai FragmentStatePagerAdapter. Se stai solo visualizzando 3 "schede" che non contengono molti dati pesanti (come Bitmaps), allora FragmentPagerAdapterpotrebbe adattarti bene. Inoltre, tieni presente che ViewPagerper impostazione predefinita caricherà 3 frammenti in memoria. Il primo Adapterche menzioni potrebbe distruggere la Viewgerarchia e ricaricarlo quando necessario, il secondo Adaptersalva solo lo stato del Fragmente lo distrugge completamente, se l'utente torna a quella pagina, lo stato viene recuperato.


Ho più pulsanti e visualizzazioni di testo in Fragment1 e ListView che generano elementi in modo dinamico in Fragment2 e Fragment3. Pensi che sia una buona idea usare FragmentStatePagerAdapter e archiviare tutti i dati in Activity, passandoli a Fragments tramite Bundle?
AlexMomotov,

2
@AlexMomotov Le viste nel layout del frammento non hanno nulla a che fare con la scelta di FragmentStatePagerAdapter. La domanda qui è la quantità di frammenti che verranno sfogliati.
IgorGanapolsky,

1
Quindi in pratica non c'è nulla a favore di FragmentPagerAdapterusarlo.
Tomasz Mularczyk,

3
Il vantaggio di @Tomasz FragmentPagerAdapterè che il passaggio da un frammento all'altro potrebbe essere molto più veloce, poiché gli Fragmentoggetti reali non devono essere ricostruiti ogni volta. D'altra parte, ciò finirebbe per usare più memoria che contiene gli oggetti frammento in memoria.
Richard Le Mesurier,

Ho 3 schede / pagine (che mostrano ciascuna una WebView), quindi ho usato FragmentPagerAdapter . Tuttavia, l'ultima pagina viene ancora ridisegnata quando scorro verso di essa dalla prima pagina. Per risolvere questo, ho usato viewPager.setOffscreenPageLimit(2).
divieto di geoingegneria il

131
  • FragmentPagerAdaptermemorizza l'intero frammento in memoria e potrebbe aumentare un sovraccarico di memoria se si utilizza una grande quantità di frammenti ViewPager.

  • Al contrario suo fratello, FragmentStatePagerAdaptermemorizza solo lo stato di istanza salvato di frammenti e distrugge tutti i frammenti quando perdono la concentrazione.

  • Pertanto FragmentStatePagerAdapterdovrebbe essere usato quando dobbiamo usare frammenti dinamici, come frammenti con widget, poiché i loro dati potrebbero essere archiviati in savedInstanceState. Inoltre non influirà sulle prestazioni anche se ci sono molti frammenti.

  • Al contrario, il fratello FragmentPagerAdapterdovrebbe essere usato quando abbiamo bisogno di conservare l'intero frammento in memoria.

  • Quando dico che l'intero frammento viene tenuto in memoria significa che le sue istanze non verranno distrutte e creerebbe un sovraccarico di memoria. Pertanto si consiglia di utilizzare FragmentPagerAdaptersolo quando vi è un basso numero di frammenti per ViewPager.

  • Sarebbe ancora meglio se i frammenti fossero statici, dal momento che non avrebbero una grande quantità di oggetti le cui istanze sarebbero archiviate.

Per essere più dettagliati,

FragmentStatePagerAdapter:

  • con FragmentStatePagerAdapter, il frammento non necessario viene distrutto. Una transazione è impegnata a rimuovere completamente il frammento dalla tua attività FragmentManager.

  • Lo stato FragmentStatePagerAdapterviene dal fatto che salverà il tuo frammento Bundleda savedInstanceStatequando viene distrutto. Quando l'utente torna indietro, il nuovo frammento verrà ripristinato usando lo stato del frammento.

FragmentPagerAdapter:

  • In confronto FragmentPagerAdapter, non fa nulla del genere. Quando il frammento non è più necessario. FragmentPagerAdapterchiama detach(Fragment)la transazione anziché remove(Fragment).

  • Questo distrugge la visione del frammento ma lascia viva l'istanza del frammento nel. FragmentManagerCosì i frammenti creati nel FragmentPagerAdapternon vengono mai distrutti.


2
Perché hai 2 risposte?
Jared Burrows,

qual è il vantaggio di mantenere interi frammenti in memoria?
Tomasz Mularczyk,

4
@Tomek: se il frammento successivo è già istanziato (ad esempio FragmentPagerAdapter), sarà pronto per il rendering quando scorri su di esso, quindi l'animazione dello scorrimento sarà più fluida. Con FragmentStatePagerAdapter, la prossima istanza di frammento potrebbe non esistere fino a quando non scorri verso di essa, e se si tratta di un grosso frammento che è costoso da creare, potresti vedere una balbuzie nell'animazione. È una questione di prestazioni rispetto al consumo di memoria.
Dalbergia,

1
@Jared Burrows perché uno è solo AnswerText che è buono per le risposte piccole e statiche e l'altro è AnswerStateText che è per risposte più grandi e dinamiche
Simple Fellow

48

Ecco un ciclo di vita del registro di ogni frammento in ViewPagercui sono presenti 4 frammenti eoffscreenPageLimit = 1 (default value)

FragmentStatePagerAdapter

Vai a Fragment1 (attività di lancio)

Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart

Vai a Frammento2

Fragment3: onCreateView
Fragment3: onStart

Vai a Frammento3

Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach
Fragment4: onCreateView
Fragment4: onStart

Vai a Frammento4

Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy

FragmentPagerAdapter

Vai a Fragment1 (attività di lancio)

Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart

Vai a Frammento2

Fragment3: onCreateView
Fragment3: onStart

Vai a Frammento3

Fragment1: onStop
Fragment1: onDestroyView
Fragment4: onCreateView
Fragment4: onStart

Vai a Frammento4

Fragment2: onStop
Fragment2: onDestroyView

Conclusione : FragmentStatePagerAdapterchiama onDestroyquando il frammento viene superato, offscreenPageLimitmentre FragmentPagerAdapternon lo è.

Nota : penso che dovremmo usare FragmentStatePagerAdapterper un ViewPagerche ha molte pagine perché andrà bene per le prestazioni.

Esempio di offscreenPageLimit:

Se andiamo a Fragment3, esso sarà Detroy Fragment1 (o Fragment5 se abbia) perché offscreenPageLimit = 1. Se poniamo offscreenPageLimit > 1che non distruggerà.
Se in questo esempio, impostiamo offscreenPageLimit=4, non c'è differenza tra l'utilizzo FragmentStatePagerAdaptero FragmentPagerAdapterperché il frammento non chiama mai onDestroyViewe onDestroyquando cambiamo scheda

Demo di Github qui


Un ottimo modo per concludere!
Rahul Rastogi,

bella spiegazione
gourav singhal

1
Bella spiegazione. Hai detto che usare FragmentStatePagerAdapter quando si hanno molte pagine è buono per le prestazioni. Intendevi dire che è buono per il salvataggio della memoria? L'obiettivo, a quanto ho capito, è quello di preservare la memoria in caso di possibili molte istanze di frammento, quindi le prestazioni sono il vantaggio implicito; l'obiettivo esplicito è preservare la memoria
Hatzil,

38

Qualcosa che non è esplicitamente detto nella documentazione o nelle risposte in questa pagina (anche se implicito da @Naruto), è che FragmentPagerAdapternon aggiornerà i frammenti se i dati nel frammento cambiano perché mantiene il frammento in memoria.

Quindi, anche se hai un numero limitato di frammenti da visualizzare, se vuoi essere in grado di aggiornare i tuoi frammenti (ad esempio, esegui nuovamente la query per aggiornare listView nel frammento), devi usare FragmentStatePagerAdapter.

Il mio punto qui è che il numero di frammenti e se sono simili o meno non è sempre l'aspetto chiave da considerare. La chiave è anche se i frammenti sono dinamici.


Quindi supponiamo di avere 2 frammenti, 1 riciclista nel frammento A, quando faccio clic su un elemento cambia il contenuto del frammento B, dico che faccio fragB.setText ("blablabla"). Dovrei usare lo stato pagerthen?
Ced

Non sono sicuro ma direi di sì. Basta provare entrambi, è davvero facile e veloce cambiare il codice da uno all'altro comunque.
JDenais,

@JDenais Sei sicuro che sia corretto? Sto usando FragmentPagerAdapternella mia attività che utilizza un ViewPager per mostrare due frammenti, in cui ogni frammento contiene un elenco. Il mio primo elenco si chiama "Tutti i rapporti" e il secondo è "Rapporti preferiti". Nel primo elenco, se tocco l'icona a forma di stella per un rapporto, aggiorna il database per cambiare lo stato preferito di quel rapporto. Scorro quindi attraverso e vedo correttamente questo rapporto nell'interfaccia utente del secondo elenco. Quindi forse le istanze vengono mantenute in memoria, ma in alcuni casi (ad es. La mia) il contenuto verrà effettivamente aggiornato correttamente per FragmentPagerAdapter
ban-geoengineering

14

FragmentPagerAdaptermemorizza i dati precedenti che vengono recuperati dall'adattatore mentre FragmentStatePagerAdapterprende il nuovo valore dall'adattatore ogni volta che viene eseguito.


4

FragmentStatePagerAdapter = Per contenere un gran numero di frammenti in ViewPager. Poiché questo adattatore distrugge il frammento quando non è visibile per l'utente e solo salvatoInstanceState del frammento viene conservato per un ulteriore utilizzo. In questo modo viene utilizzata una bassa quantità di memoria e vengono fornite prestazioni migliori in caso di frammenti dinamici.


1

FragmentPagerAdapter : il frammento di ogni pagina visitata dall'utente verrà archiviato in memoria, anche se la vista verrà distrutta. Pertanto, quando la pagina è nuovamente visibile, la vista verrà ricreata ma l'istanza del frammento non verrà ricreata. Ciò può comportare l'utilizzo di una notevole quantità di memoria. FragmentPagerAdapter dovrebbe essere usato quando abbiamo bisogno di memorizzare l'intero frammento in memoria. FragmentPagerAdapter chiama staccare (Frammento) sulla transazione invece di rimuovere (Frammento).

FragmentStatePagerAdapter : l'istanza del frammento viene distrutta quando non è visibile per l'utente, tranne lo stato salvato del frammento. Ciò comporta l'utilizzo di una piccola quantità di memoria e può essere utile per gestire set di dati più grandi. Dovrebbe essere usato quando dobbiamo usare frammenti dinamici, come frammenti con widget, poiché i loro dati potrebbero essere memorizzati nell'istanza salvata.Inoltre, ciò non influirà sulle prestazioni anche se ci sono molti frammenti.

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.