wake-up-neo.com

Was ist der Unterschied zwischen FragmentPagerAdapter und FragmentStatePagerAdapter?

Was ist der Unterschied zwischen FragmentPagerAdapter und FragmentStatePagerAdapter?

Über FragmentPagerAdapter Googles Leitfaden sagt:

Diese Version des Pagers eignet sich am besten, wenn eine Handvoll von normalerweise statischeren Fragmenten durchgeblättert werden muss, z. B. eine Reihe von Registerkarten. Das Fragment jeder Seite, die der Benutzer besucht, bleibt im Speicher, obwohl die Ansichtshierarchie zerstört werden kann, wenn sie nicht sichtbar ist. Dies kann zu einem erheblichen Speicherbedarf führen, da Fragmentinstanzen eine beliebige Menge an Status beibehalten können. Betrachten Sie für größere Seitensätze FragmentStatePagerAdapter.

Und über FragmentStatePagerAdapter:

Diese Version des Pagers ist nützlicher, wenn eine große Anzahl von Seiten vorhanden ist und eher wie eine Listenansicht funktioniert. Wenn Seiten für den Benutzer nicht sichtbar sind, wird möglicherweise das gesamte Fragment zerstört, wobei nur der gespeicherte Status dieses Fragments beibehalten wird. Auf diese Weise kann der Pager im Vergleich zu FragmentPagerAdapter viel weniger Speicherplatz für jede aufgerufene Seite bereithalten, was möglicherweise zu einem höheren Overhead beim Seitenwechsel führt.

Ich habe also nur 3 Fragmente. Aber alle sind separate Module mit einer großen Datenmenge.

Fragment1 verarbeitet einige Daten (die Benutzer eingeben) und übergibt sie per Aktivität an Fragment2, das ist nur ein einfaches ListFragment. Fragment3 ist auch ein ListFragment.

Also meine Fragen sind: Welchen Adapter soll ich verwenden? FragmentPagerAdapter oder FragmentStatePagerAdapter?

340
AlexMomotov

Denken Sie, wie die Ärzte sagen, so darüber nach. Wenn Sie eine Anwendung wie einen Buchleser ausführen, möchten Sie nicht alle Fragmente auf einmal in den Speicher laden. Sie möchten Fragments laden und zerstören, während der Benutzer liest. In diesem Fall verwenden Sie FragmentStatePagerAdapter. Wenn Sie nur 3 "Registerkarten" anzeigen, die nicht viele wichtige Daten enthalten (z. B. Bitmaps), passt FragmentPagerAdapter möglicherweise zu Ihnen. Denken Sie auch daran, dass ViewPager standardmäßig 3 Fragmente in den Speicher lädt. Das erste Adapter, das Sie erwähnen, kann die View -Hierarchie zerstören und bei Bedarf neu laden, das zweite Adapter speichert nur den Zustand des Fragment und zerstört ihn vollständig Wenn der Benutzer dann zu dieser Seite zurückkehrt, wird der Status abgerufen.

274
Emmanuel
  • FragmentPagerAdapter speichert das gesamte Fragment im Speicher und kann den Speicheraufwand erhöhen, wenn in ViewPager eine große Anzahl von Fragmenten verwendet wird.

  • Im Gegensatz zu seinen Geschwistern speichert FragmentStatePagerAdapter nur den gespeicherten Instanzstatus von Fragmenten und zerstört alle Fragmente, wenn sie den Fokus verlieren.

  • Daher sollte FragmentStatePagerAdapter verwendet werden, wenn dynamische Fragmente verwendet werden müssen, wie z. B. Fragmente mit Widgets, da deren Daten in savedInstanceState gespeichert werden können. Auch wenn eine große Anzahl vorhanden ist, wird die Leistung nicht beeinträchtigt von Fragmenten.

  • Im Gegensatz dazu sollte sein Geschwister FragmentPagerAdapter verwendet werden, wenn das gesamte Fragment im Speicher abgelegt werden soll.

  • Wenn ich sage, dass das gesamte Fragment im Speicher bleibt, bedeutet dies, dass seine Instanzen nicht zerstört werden und einen Speicher-Overhead verursachen würden. Aus diesem Grund wird empfohlen, FragmentPagerAdapter nur zu verwenden, wenn für ViewPager nur eine geringe Anzahl von Fragmenten vorhanden ist.

  • Es wäre sogar noch besser, wenn die Fragmente statisch wären, da sie nicht viele Objekte enthalten würden, deren Instanzen gespeichert würden.

Um genauer zu sein,

FragmentStatePagerAdapter:

  • mit FragmentStatePagerAdapter wird Ihr nicht benötigtes Fragment zerstört. Mit einer Transaktion wird das Fragment vollständig aus dem FragmentManager Ihrer Aktivität entfernt.

  • Der Status in FragmentStatePagerAdapter ergibt sich aus der Tatsache, dass das Bundle Ihres Fragments aus savedInstanceState gespeichert wird, wenn es zerstört wird. Wenn der Benutzer zurück navigiert, wird das neue Fragment wiederhergestellt mit dem Zustand des Fragments.

FragmentPagerAdapter:

  • Durch Vergleich macht FragmentPagerAdapter nichts dergleichen. Wenn das Fragment nicht mehr benötigt wird. FragmentPagerAdapter ruft detach(Fragment) für die Transaktion anstelle von remove(Fragment) auf.

  • Dadurch wird die Ansicht des Fragments zerstört, aber die Instanz des Fragments bleibt in FragmentManager am Leben, sodass die in FragmentPagerAdapter erstellten Fragmente niemals zerstört werden.

120
Stephen

Etwas, das nicht explizit in der Dokumentation oder in den Antworten auf dieser Seite erwähnt wird (obwohl dies von @Naruto impliziert wird), ist, dass FragmentPagerAdapter die Fragmente nicht aktualisiert, wenn sich die Daten im Fragment ändern, weil das Fragment erhalten bleibt in Erinnerung.

Selbst wenn Sie eine begrenzte Anzahl von Fragmenten anzeigen möchten, müssen Sie FragmentStatePagerAdapter verwenden, um Ihre Fragmente aktualisieren zu können (z. B. um die Abfrage erneut auszuführen, um die ListView im Fragment zu aktualisieren).

Mein ganzer Punkt hier ist, dass die Anzahl der Fragmente und ob sie ähnlich sind oder nicht, nicht immer der entscheidende Aspekt ist. Es ist auch entscheidend, ob Ihre Fragmente dynamisch sind oder nicht.

36
JDenais

Hier ist ein Protokolllebenszyklus jedes Fragments in ViewPager mit 4 Fragmenten und offscreenPageLimit = 1 (default value)

FragmentStatePagerAdapter

Gehe zu Fragment1 (Startaktivität)

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

Gehe zu Fragment2

Fragment3: onCreateView
Fragment3: onStart

Gehe zu Fragment3

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

Gehe zu Fragment4

Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy

FragmentPagerAdapter

Gehe zu Fragment1 (Startaktivität)

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

Gehe zu Fragment2

Fragment3: onCreateView
Fragment3: onStart

Gehe zu Fragment3

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

Gehe zu Fragment4

Fragment2: onStop
Fragment2: onDestroyView

Fazit: FragmentStatePagerAdapter ruft onDestroy auf, wenn das Fragment überwunden ist offscreenPageLimit, während FragmentPagerAdapter nicht.

Hinweis: Ich denke, wir sollten FragmentStatePagerAdapter für eine ViewPager verwenden, die eine Menge Seiten enthält, da dies für die Leistung gut ist.

Beispiel von offscreenPageLimit:

Wenn wir zu Fragment3 gehen, wird wird Fragment1 (oder Fragment5, falls vorhanden) detroyen, weil offscreenPageLimit = 1. Wenn wir offscreenPageLimit > 1 es wird nicht zerstören.
Wenn wir in diesem Beispiel offscreenPageLimit=4, es gibt keinen Unterschied zwischen der Verwendung von FragmentStatePagerAdapter oder FragmentPagerAdapter, da Fragment niemals onDestroyView und onDestroy aufruft, wenn wir die Registerkarte wechseln

Github Demo hier

33
Phan Van Linh

FragmentPagerAdapter speichert die vorherigen Daten, die vom Adapter abgerufen werden, während FragmentStatePagerAdapter bei jeder Ausführung den neuen Wert vom Adapter übernimmt.

14
vinay kumar

FragmentStatePagerAdapter = Um eine große Anzahl von Fragmenten in ViewPager aufzunehmen. Da dieser Adapter das Fragment zerstört, wenn es für den Benutzer nicht sichtbar ist und nur der SavedInstanceState des Fragments zur weiteren Verwendung aufbewahrt wird. Auf diese Weise wird wenig Arbeitsspeicher verwendet und bei dynamischen Fragmenten eine bessere Leistung erzielt.

4
Dwivedi Ji