réutiliser des fragments dans un fragmentpageradapter

J’ai un viewpager qui parcourt des fragments. Ma sous-classe FragmentPagerAdapter crée un nouveau fragment dans la méthode getItem qui semble inutile. Existe-t-il un FragmentPagerAdapter équivalent à convertView dans le listAdapter qui me permettra de réutiliser des fragments déjà créés? Mon code est ci-dessous.

 public class ProfilePagerAdapter extends FragmentPagerAdapter { ArrayList mProfiles = new ArrayList(); public ProfilePagerAdapter(FragmentManager fm) { super(fm); } /** * Adding a new profile object created a new page in the pager this adapter is set to. * @param profile */ public void addProfile(Profile profile){ mProfiles.add(profile); } @Override public int getCount() { return mProfiles.size(); } @Override public Fragment getItem(int position) { return new ProfileFragment(mProfiles.get(position)); } } 

FragmentPagerAdapter met déjà en cache les Fragments pour vous. Chaque fragment se voit atsortingbuer une balise, puis FragmentPagerAdapter essaie d’appeler findFragmentByTag . Il appelle seulement getItem si le résultat de findFragmentByTag est null . Donc, vous ne devriez pas avoir à mettre les fragments en cache vous-même.

Annexe pour le post de Geoff:

Vous pouvez obtenir une référence à votre Fragment dans FragmentPagerAdapter utilisant findFragmentByTag() . Le nom de la balise est généré de cette façon:

 private static Ssortingng makeFragmentName(int viewId, int index) { return "android:switcher:" + viewId + ":" + index; } 

où viewId est l’identifiant de ViewPager

Regardez ce lien: http://code.google.com/p/openintents/source/browse/trunk/compatibility/AndroidSupportV2/src/android/support/v2/app/FragmentPagerAdapter.java#104

Il semble que beaucoup de personnes qui consultent cette question cherchent un moyen de référencer les Fragments créés par FragmentPagerAdapter / FragmentStatePagerAdapter . Je voudrais offrir ma solution à cela sans compter sur les tags créés en interne que les autres réponses utilisent ici.

En bonus, cette méthode devrait également fonctionner avec FragmentStatePagerAdapter . Voir les notes ci-dessous pour plus de détails.


Problème avec les solutions actuelles: s’appuyer sur du code interne

Un grand nombre des solutions que j’ai vues sur cette question et des questions similaires reposent sur l’obtention d’une référence au Fragment existant en appelant FragmentManager.findFragmentByTag() et en imitant la balise créée en interne: "android:switcher:" + viewId + ":" + id . Le problème est que vous vous fiez au code source interne, ce qui, comme nous le soaps tous, n’est pas garanti pour toujours. Les ingénieurs Android de Google pourraient facilement décider de modifier la structure des tag , ce qui vous empêcherait de trouver une référence aux Fragments existants.

Solution alternative sans compter sur la tag interne

Voici un exemple simple de la façon d’obtenir une référence aux Fragments retournés par FragmentPagerAdapter qui ne repose pas sur les tags internes définies sur les Fragments . La clé est de remplacer instantiateItem() et d’enregistrer des références dans ces getItem() plutôt que dans getItem() .

 public class SomeActivity extends Activity { private FragmentA m1stFragment; private FragmentB m2ndFragment; // other code in your Activity... private class CustomPagerAdapter extends FragmentPagerAdapter { // other code in your custom FragmentPagerAdapter... public CustomPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { // Do NOT try to save references to the Fragments in getItem(), // because getItem() is not always called. If the Fragment // was already created then it will be resortingeved from the FragmentManger // and not here (ie getItem() won't be called again). switch (position) { case 0: return new FragmentA(); case 1: return new FragmentB(); default: // This should never happen. Always account for each position above return null; } } // Here we can finally safely save a reference to the created // Fragment, no matter where it came from (either getItem() or // FragmentManger). Simply save the returned Fragment from // super.instantiateItem() into an appropriate reference depending // on the ViewPager position. @Override public Object instantiateItem(ViewGroup container, int position) { Fragment createdFragment = (Fragment) super.instantiateItem(container, position); // save the appropriate reference depending on position switch (position) { case 0: m1stFragment = (FragmentA) createdFragment; break; case 1: m2ndFragment = (FragmentB) createdFragment; break; } return createdFragment; } } public void someMethod() { // do work on the referenced Fragments, but first check if they // even exist yet, otherwise you'll get an NPE. if (m1stFragment != null) { // m1stFragment.doWork(); } if (m2ndFragment != null) { // m2ndFragment.doSomeWorkToo(); } } } 

ou si vous préférez travailler avec des tags au lieu de variables / références de membres de classe aux Fragments vous pouvez également saisir les tags définies par FragmentPagerAdapter de la même manière: REMARQUE: cela ne s’applique pas à FragmentStatePagerAdapter car il ne définit pas de tags ses Fragments .

 @Override public Object instantiateItem(ViewGroup container, int position) { Fragment createdFragment = (Fragment) super.instantiateItem(container, position); // get the tags set by FragmentPagerAdapter switch (position) { case 0: Ssortingng firstTag = createdFragment.getTag(); break; case 1: Ssortingng secondTag = createdFragment.getTag(); break; } // ... save the tags somewhere so you can reference them later return createdFragment; } 

Notez que cette méthode ne repose pas sur la reproduction de la tag interne définie par FragmentPagerAdapter et utilise à la place des API appropriées pour les récupérer. De cette façon, même si la tag change dans les futures versions de la SupportLibrary vous serez toujours en sécurité.


N’oubliez pas qu’en fonction de la conception de votre Activity , les Fragments sur lesquels vous essayez de travailler peuvent ne pas exister, vous devez donc en tenir compte en effectuant null vérifications null avant d’utiliser vos références.

De plus, si au lieu de cela vous travaillez avec FragmentStatePagerAdapter , vous ne souhaitez pas conserver de références précises à vos Fragments car vous pourriez en avoir beaucoup et les références matérielles les garderaient inutilement en mémoire. Au lieu de cela, enregistrez les références de Fragment dans les variables WeakReference au lieu des variables standard. Comme ça:

 WeakReference m1stFragment = new WeakReference(createdFragment); // ...and access them like so Fragment firstFragment = m1stFragment.get(); if (firstFragment != null) { // reference hasn't been cleared yet; do work... } 

Si le fragment est encore en mémoire, vous pouvez le trouver avec cette fonction.

 public Fragment findFragmentByPosition(int position) { FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter(); return getSupportFragmentManager().findFragmentByTag( "android:switcher:" + getViewPager().getId() + ":" + fragmentPagerAdapter.getItemId(position)); } 

Exemple de code pour api de support v4.

Je sais que ce n’est (théoriquement) pas une réponse à la question, mais une approche différente.

J’ai eu un problème où je devais rafraîchir les fragments visibles. Tout ce que j’ai essayé, a échoué et a échoué lamentablement …

Après avoir essayé tellement de choses différentes, j’ai finalement terminé avec BroadCastReceiver . Envoyez simplement une émission lorsque vous devez faire quelque chose avec les fragments visibles et la capturer dans le fragment.

Si vous avez également besoin d’une réponse, vous pouvez également l’envoyer par diffusion.

à votre santé