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
?
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é.
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.
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.
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
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. 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.