web-dev-qa-db-fra.com

Quelle est la différence entre FragmentPagerAdapter et FragmentStatePagerAdapter?

Quelle est la différence entre FragmentPagerAdapter et FragmentStatePagerAdapter?

À propos de FragmentPagerAdapter Le guide de Google indique:

Cette version du téléavertisseur est particulièrement utile lorsque vous devez parcourir une poignée de fragments généralement plus statiques, tels qu'un ensemble d'onglets. Le fragment de chaque page visitée par l'utilisateur sera conservé en mémoire, même si sa hiérarchie de vues peut être détruite si elle n'est pas visible. Cela peut entraîner l'utilisation d'une quantité importante de mémoire, car les instances de fragment peuvent conserver une quantité d'état arbitraire. Pour les grands ensembles de pages, considérez FragmentStatePagerAdapter.

Et à propos de FragmentStatePagerAdapter:

Cette version du pager est plus utile quand il y a un grand nombre de pages, fonctionnant plutôt comme une vue liste. Lorsque les pages ne sont pas visibles par l'utilisateur, leur fragment entier peut être détruit, ne conservant que l'état de sauvegarde de ce fragment. Cela permet au pageur de conserver beaucoup moins de mémoire associée à chaque page visitée par rapport à FragmentPagerAdapter au prix d’une surcharge supplémentaire lors du passage d’une page à l’autre.

Donc, je n'ai que 3 fragments. Mais tous sont des modules séparés avec une grande quantité de données.

Fragment1 traite certaines données (que les utilisateurs saisissent) et les transmet via activité à Fragment2, qui est simplement un simple ListFragment. Fragment3 est également un ListFragment.

Donc mes questions sont: Quel adaptateur dois-je utiliser? FragmentPagerAdapter ou FragmentStatePagerAdapter?

340
AlexMomotov

Comme le disent les docs, réfléchissez de cette façon. Si vous deviez faire une application comme un lecteur de livre, vous ne voudrez pas charger tous les fragments en mémoire à la fois. Vous souhaitez charger et détruire Fragments au fur et à mesure que l'utilisateur le lit. Dans ce cas, vous utiliserez FragmentStatePagerAdapter. Si vous n’affichez que 3 "onglets" ne contenant pas beaucoup de données lourdes (comme Bitmaps), alors FragmentPagerAdapter pourrait vous convenir. Aussi, gardez à l'esprit que ViewPager par défaut chargera 3 fragments en mémoire. La première Adapter que vous mentionnez peut détruire la hiérarchie View et la recharger en cas de besoin, la seconde Adapter enregistre uniquement l'état de la Fragment et la détruit complètement, si l'utilisateur revient ensuite à cette page, l'état est récupéré.

274
Emmanuel
  • FragmentPagerAdapter stocke le fragment entier dans la mémoire et peut augmenter la surcharge de la mémoire si une grande quantité de fragments est utilisée dans ViewPager.

  • Au contraire de son frère, FragmentStatePagerAdapter ne stocke que l'état sauvegardé d'instance de fragments et détruit tous les fragments lorsqu'ils perdent le focus.

  • Par conséquent, FragmentStatePagerAdapter devrait être utilisé lorsque nous devons utiliser des fragments dynamiques, tels que des fragments avec des widgets, car leurs données pourraient être stockées dans le savedInstanceState. .

  • Au contraire, son frère FragmentPagerAdapter devrait être utilisé lorsque nous avons besoin de stocker le fragment entier en mémoire.

  • Quand je dis que le fragment entier est gardé en mémoire, cela signifie que ses instances ne seront pas détruites et créeraient un surcoût de mémoire. Par conséquent, il est conseillé d'utiliser FragmentPagerAdapter uniquement lorsque le nombre de fragments pour ViewPager est faible.

  • Il serait même préférable que les fragments soient statiques, car ils n'auraient pas une grande quantité d'objets dont les occurrences seraient stockées.

Pour être plus en détail,

FragmentStatePagerAdapter:

  • avec FragmentStatePagerAdapter, votre fragment inutile est détruit. Une transaction est engagée pour supprimer complètement le fragment de votre activité FragmentManager.

  • L'état dans FragmentStatePagerAdapter provient du fait qu'il sauvegardera le fragment Bundle de savedInstanceState de votre fragment lorsqu'il sera détruit. Lorsque l'utilisateur reviendra en arrière, le nouveau fragment sera restauré à l'aide de celui-ci. Etat.

FragmentPagerAdapter:

  • Par comparaison, FragmentPagerAdapter ne fait rien du genre. Quand le fragment n'est plus nécessaire .FragmentPagerAdapter appelle detach(Fragment) sur la transaction à la place de remove(Fragment).

  • Ceci détruit la vue du fragment mais laisse son instance vivante dans le FragmentManager. Ainsi, les fragments créés dans le FragmentPagerAdapter ne sont jamais détruits.

120
Stephen

Quelque chose qui n’est pas explicitement indiqué dans la documentation ou dans les réponses de cette page (même si cela est impliqué par @Naruto), c’est que FragmentPagerAdapter ne mettra pas à jour les fragments si les données du fragment changent car ils conservent le fragment Mémoire.

Ainsi, même si vous avez un nombre limité de fragments à afficher, si vous souhaitez pouvoir actualiser vos fragments (par exemple, ré-exécutez la requête pour mettre à jour le listView dans le fragment), vous devez utiliser FragmentStatePagerAdapter.

Tout ce que je veux dire ici, c'est que le nombre de fragments et leur ressemblance ne sont pas toujours l'aspect clé à prendre en compte. Que vos fragments soient dynamiques ou non est également essentiel.

36
JDenais

Voici un journal du cycle de vie de chaque fragment dans ViewPager qui a 4 fragments et offscreenPageLimit = 1 (default value)

FragmentStatePagerAdapter

Aller à Fragment1 (activité de lancement)

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

Aller au fragment2

Fragment3: onCreateView
Fragment3: onStart

Aller à Fragment3

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

Aller au fragment4

Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy

FragmentPagerAdapter

Aller à Fragment1 (activité de lancement)

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

Aller au fragment2

Fragment3: onCreateView
Fragment3: onStart

Aller à Fragment3

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

Aller au fragment4

Fragment2: onStop
Fragment2: onDestroyView

Conclusion : FragmentStatePagerAdapter appelez onDestroy lorsque le fragment est surmonté offscreenPageLimit tandis que FragmentPagerAdapter ne l'est pas.

Note : Je pense que nous devrions utiliser FragmentStatePagerAdapter pour un ViewPager qui a beaucoup de pages car il sera bon pour la performance.

Exemple de offscreenPageLimit:

Si nous allons à Fragment3, il détruira Fragment1 (ou Fragment5 si have) car offscreenPageLimit = 1. Si nous définissons offscreenPageLimit > 1, il ne sera pas détruit.
Si dans cet exemple, nous définissons offscreenPageLimit=4, il n'y a pas de différence entre utiliser FragmentStatePagerAdapter ou FragmentPagerAdapter car Fragment n'appelle jamais onDestroyView et onDestroy quand on change d'onglet

démo Github ici

33
Phan Van Linh

FragmentPagerAdapter stocke les données précédentes extraites de l'adaptateur, tandis que FragmentStatePagerAdapter prend la nouvelle valeur de l'adaptateur à chaque exécution.

14
vinay kumar

FragmentStatePagerAdapter = Pour accueillir un grand nombre de fragments dans ViewPager. En tant que cet adaptateur détruit le fragment lorsqu'il n'est pas visible par l'utilisateur et que seul savedInstanceState du fragment est conservé pour une utilisation ultérieure. De cette manière, une faible quantité de mémoire est utilisée et de meilleures performances sont délivrées en cas de fragments dynamiques.

4
Dwivedi Ji