Différence entre FragmentPagerAdapter et FragmentStatePagerAdapter

Quelle est la différence entre FragmentPagerAdapter et FragmentStatePagerAdapter ?

À propos de FragmentPagerAdapter Le guide de Google dit:

Cette version du paginateur est idéale pour utiliser une poignée de fragments généralement plus statiques, tels qu’un ensemble d’tabs. Le fragment de chaque page que l’utilisateur visite sera conservé en mémoire, bien que sa hiérarchie de vue puisse ê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 fragments peuvent conserver une quantité arbitraire d’état. Pour les plus grands ensembles de pages, considérez FragmentStatePagerAdapter.

Et à propos de FragmentStatePagerAdapter :

Cette version du pagineur est plus utile lorsqu’il existe un grand nombre de pages, fonctionnant plutôt comme une vue liste. Lorsque les pages ne sont pas visibles pour l’utilisateur, leur fragment entier peut être détruit, ne conservant que l’état enregistré 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 potentiellement plus importante lors du passage d’une page à l’autre.

Donc, j’ai juste 3 fragments. Mais tous sont des modules séparés avec une grande quantité de données.

Fragment1 gère certaines données (que les utilisateurs entrent) et les transmet via l’activité à Fragment2 , qui est juste un simple ListFragment . Fragment3 est aussi un ListFragment .

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

Comme le disent les médecins, pensez-y de cette façon. Si vous deviez faire une application comme un lecteur de livre, vous ne voudriez pas charger tous les fragments en mémoire en même temps. Vous souhaitez charger et détruire les Fragments fur et à mesure que l’utilisateur lit. Dans ce cas, vous utiliserez FragmentStatePagerAdapter . Si vous Bitmaps simplement 3 “tabs” qui ne contiennent pas beaucoup de données lourdes (comme les Bitmaps ), alors FragmentPagerAdapter pourrait vous convenir. De plus, gardez à l’esprit que ViewPager par défaut chargera 3 fragments en mémoire. Le premier Adapter vous mentionnez peut détruire la hiérarchie de View et la recharger lorsque cela est nécessaire. Le second Adapter enregistre uniquement l’état du Fragment et le détruit complètement. Si l’utilisateur revient alors à cette page, l’état est récupéré.

  • FragmentPagerAdapter stocke l’intégralité du fragment en mémoire et peut augmenter la charge 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 In-stockState des fragments et détruit tous les fragments lorsqu’ils perdent le focus.

  • Par conséquent, FragmentStatePagerAdapter doit être utilisé lorsque nous devons utiliser des fragments dynamics, tels que des fragments avec des widgets, car leurs données pourraient être stockées dans le savedInstanceState . De même, cela n’affectera pas les performances même s’il existe un grand nombre de fragments.

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

  • Lorsque je dis que tout le fragment est conservé en mémoire, cela signifie que ses instances ne seront pas détruites et créeraient une surcharge de mémoire. Par conséquent, il est conseillé d’utiliser FragmentPagerAdapter uniquement lorsque le nombre de fragments de ViewPager .

  • Ce serait encore mieux si les fragments étaient statiques, car ils n’auraient pas beaucoup d’objects dont les instances seraient stockées.

Ê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 du gestionnaire de fragmentation de votre activité.

  • L’état dans FragmentStatePagerAdapter vient du fait qu’il sauvera le Bundle de votre fragment de savedInstanceState lorsqu’il sera détruit. Lorsque l’utilisateur naviguera à nouveau, le nouveau fragment sera restauré en utilisant l’état du fragment.

FragmentPagerAdapter:

  • Par comparaison, FragmentPagerAdapter ne fait rien de tel. Lorsque le fragment n’est plus nécessaire. FragmentPagerAdapter appelle detach(Fragment) sur la transaction au lieu de la remove(Fragment) .

  • Cette destruction est la vue du fragment mais laisse en vie l’instance du fragment dans FragmentManager Ainsi, les fragments créés dans FragmentPagerAdapter ne sont jamais détruits.

Quelque chose qui n’est pas explicitement mentionné dans la documentation ou dans les réponses sur cette page (même si @Naruto l’indique) est que FragmentPagerAdapter ne mettra pas à jour les Fragments si les données du Fragment changent car le Fragment rest en mémoire.

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

Ce que je veux dire, c’est que le nombre de fragments et leur similarité ou non n’est pas toujours l’aspect clé à considérer. Que vos fragments soient ou non dynamics est également essentiel.

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

FragmentStatePagerAdapter

Aller au fragment1 (activité de lancement)

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

Aller au fragment2

 Fragment3: onCreateView Fragment3: onStart 

Aller au fragment3

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

Aller au fragment4

 Fragment2: onStop Fragment2: onDestroyView Fragment2: onDestroy 

FragmentPagerAdapter

Aller au fragment1 (activité de lancement)

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

Aller au fragment2

 Fragment3: onCreateView Fragment3: onStart 

Aller au fragment3

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

Aller au fragment4

 Fragment2: onStop Fragment2: onDestroyView 

Conclusion : FragmentStatePagerAdapter appelle onDestroy lorsque le fragment est dépassé offscreenPageLimit alors que FragmentPagerAdapter ne l’est pas.

Note : Je pense que nous devrions utiliser FragmentStatePagerAdapter pour un ViewPager qui a beaucoup de pages, car cela sera bon pour les performances.

Exemple de offscreenPageLimit :

Si nous passons à Fragment3, cela détruira Fragment1 (ou Fragment5 si nécessaire) car offscreenPageLimit = 1 . Si on définit 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 lorsque nous changeons d’onglet

Démo Github ici

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.

FragmentStatePagerAdapter = Pour accueillir un grand nombre de fragments dans ViewPager. Comme cet adaptateur détruit le fragment lorsqu’il n’est pas visible par l’utilisateur et que seul le paramètre savedInstanceState du fragment est conservé pour une utilisation ultérieure. De cette façon, une faible quantité de mémoire est utilisée et une meilleure performance est fournie en cas de fragments dynamics.