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.