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