Quelle est la difference entre FragmentPagerAdapter
et FragmentStatePagerAdapter
?
À propos FragmentPagerAdapter
du guide de Google dit:
Cette version du pageur est préférable pour une utilisation lorsqu'il existe une poignée de fragments généralement plus statiques à parcourir, comme un ensemble d'onglets. Le fragment de chaque page visitée par l'utilisateur sera conservé en mémoire, bien que sa hiérarchie de vues puisse être détruite lorsqu'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é d'état arbitraire. Pour de plus grands ensembles de pages, considérez
FragmentStatePagerAdapter
.
Et sur FragmentStatePagerAdapter
:
Cette version du pager est plus utile quand il y a un grand nombre de pages, fonctionnant plus comme une vue de 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 téléavertisseur de conserver beaucoup moins de mémoire associée à chaque page visitée par rapport
FragmentPagerAdapter
au coût potentiellement plus élevé lors du basculement entre les pages.
Je n'ai donc que 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 saisissent) et les transmet via une activité Fragment2
, ce qui est simple ListFragment
. Fragment3
est aussi un ListFragment
.
Mes questions sont donc les suivantes : quel adaptateur dois-je utiliser? FragmentPagerAdapter
ou FragmentStatePagerAdapter
?
la source
FragmentPagerAdapter
etFragmentStatePagerAdapter
qu'est-ce que c'estFragmentStateAdapter
?Réponses:
Comme le disent les docs, pensez-y 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
pendant que l'utilisateur lit. Dans ce cas, vous utiliserezFragmentStatePagerAdapter
. Si vous affichez simplement 3 "onglets" qui ne contiennent pas beaucoup de données lourdes (commeBitmaps
), celaFragmentPagerAdapter
pourrait vous convenir. Gardez également à l'esprit queViewPager
par défaut, 3 fragments seront chargés en mémoire. Le premier queAdapter
vous mentionnez peut détruire laView
hiérarchie et la recharger si nécessaire, le secondAdapter
n'enregistre que l'état duFragment
et le détruit complètement, si l'utilisateur revient ensuite sur cette page, l'état est récupéré.la source
FragmentPagerAdapter
utiliser.FragmentPagerAdapter
que la commutation entre les fragments pourrait être beaucoup plus rapide, car lesFragment
objets réels n'ont pas besoin d'être reconstruits à chaque fois. D'un autre côté, cela finirait par utiliser plus de mémoire contenant les objets fragmentés en mémoire.viewPager.setOffscreenPageLimit(2)
.FragmentPagerAdapter
stocke le fragment entier en mémoire et pourrait augmenter la surcharge de mémoire si une grande quantité de fragments est utilisée dansViewPager
.Au contraire, son frère,
FragmentStatePagerAdapter
ne stocke que l'état sauvegardéInstanceState et détruit tous les fragments lorsqu'ils perdent le focus.Par conséquent,
FragmentStatePagerAdapter
doit être utilisé lorsque nous devons utiliser des fragments dynamiques, comme des fragments avec des widgets, car leurs données pourraient être stockées dans lesavedInstanceState
.Aussi cela n'affectera pas les performances même s'il y a un grand nombre de fragments.Au contraire, son frère
FragmentPagerAdapter
devrait être utilisé lorsque nous devons 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 une surcharge de mémoire. Par conséquent, il est conseillé de n'utiliser
FragmentPagerAdapter
que lorsque le nombre de fragments est faibleViewPager
.Ce serait encore mieux si les fragments sont statiques, car ils n'auraient pas une grande quantité d'objets dont les instances seraient stockées.
Pour être plus détaillé,
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
vient du fait qu'il sauvera votre fragmentBundle
desavedInstanceState
quand il est détruit. Lorsque l'utilisateur revient, 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
appelledetach(Fragment)
la transaction au lieu deremove(Fragment)
.Cela détruit la vue du fragment mais laisse l'instance du fragment vivante dans le
FragmentManager
.so les fragments créés dans leFragmentPagerAdapter
ne sont jamais détruits.la source
Voici un cycle de vie du journal de chaque fragment dans
ViewPager
lequel ont 4 fragments etoffscreenPageLimit = 1 (default value)
FragmentStatePagerAdapter
Allez à Fragment1 (activité de lancement)
Aller à Fragment2
Allez au Fragment3
Allez à Fragment4
FragmentPagerAdapter
Allez à Fragment1 (activité de lancement)
Aller à Fragment2
Allez au Fragment3
Allez à Fragment4
Conclusion :
FragmentStatePagerAdapter
appelezonDestroy
quand le Fragment est surmontéoffscreenPageLimit
alors queFragmentPagerAdapter
non.Remarque : je pense que nous devrions utiliser
FragmentStatePagerAdapter
pour unViewPager
qui a beaucoup de page car il sera bon pour les performances.Exemple de
offscreenPageLimit
:Si nous allons à Fragment3, il sera DETROY Fragment1 (ou si Fragment5 ont) parce que
offscreenPageLimit = 1
. Si nous le réglons,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 utiliserFragmentStatePagerAdapter
ouFragmentPagerAdapter
parce que Fragment n'appelle jamaisonDestroyView
etonDestroy
quand nous changeons d'ongletDémo Github ici
la source
Quelque chose qui n'est pas dit explicitement dans la documentation ou dans les réponses sur cette page (même si cela est implicite par @Naruto), est que
FragmentPagerAdapter
cela ne mettra pas à jour les fragments si les données dans le fragment changent parce qu'il garde le fragment en mémoire.Ainsi, même si vous avez un nombre limité de fragments à afficher, si vous souhaitez pouvoir actualiser vos fragments (par exemple, vous réexécutez la requête pour mettre à jour la listView dans le fragment), vous devez utiliser FragmentStatePagerAdapter.
Tout ce que je veux dire ici, c'est que le nombre de fragments et leur similitude ne sont pas toujours l'aspect clé à considérer. Que vos fragments soient dynamiques ou non est également essentiel.
la source
FragmentPagerAdapter
dans mon activité qui utilise un ViewPager pour afficher deux fragments - où chaque fragment contient une liste. Ma première liste est appelée "Tous les rapports" et la deuxième liste est "Rapports favoris". Dans la première liste, si je tape sur l'icône en forme d'étoile pour un rapport, il met à jour la base de données pour basculer le statut favori de ce rapport. Je glisse ensuite à travers et je vois avec succès ce rapport dans l'interface utilisateur de la deuxième liste. Alors peut-être que les instances sont conservées en mémoire mais dans certains cas (par exemple, le mien) le contenu sera effectivement mis à jour correctement pour FragmentPagerAdapterFragmentPagerAdapter
stocke les données précédentes extraites de l'adaptateur tout enFragmentStatePagerAdapter
prenant la nouvelle valeur de l'adaptateur à chaque exécution.la source
FragmentStatePagerAdapter = Pour accueillir un grand nombre de fragments dans ViewPager. Étant donné que cet adaptateur détruit le fragment lorsqu'il n'est pas visible pour l'utilisateur et seul le instance de sauvegarde du fragment est conservé pour une utilisation ultérieure. De cette façon, une faible quantité de mémoire est utilisée et de meilleures performances sont fournies en cas de fragments dynamiques.
la source
FragmentPagerAdapter : le fragment de chaque page visitée par l'utilisateur sera stocké en mémoire, bien que la vue soit détruite. Ainsi, lorsque la page est à nouveau visible, la vue est recréée mais l'instance de fragment n'est pas recréée. Cela peut entraîner une quantité importante de mémoire utilisée. FragmentPagerAdapter doit être utilisé lorsque nous devons stocker le fragment entier en mémoire. FragmentPagerAdapter appelle detach (Fragment) sur la transaction au lieu de remove (Fragment).
FragmentStatePagerAdapter : l'instance de fragment est détruite lorsqu'elle n'est pas visible pour l'utilisateur, à l'exception de l'état enregistré du fragment. Cela se traduit par l'utilisation d'une petite quantité de mémoire et peut être utile pour gérer des ensembles de données plus volumineux. Doit être utilisé lorsque nous devons utiliser des fragments dynamiques, comme des fragments avec des widgets, car leurs données pourraient être stockées dans le sharedInstanceState. De plus, cela n'affectera pas les performances même s'il y a un grand nombre de fragments.
la source