Ich habe einen Viewpager, der durch Fragmente blättert. Meine FragmentPagerAdapter
Unterklasse erstellt ein neues Fragment in der getItem
Methode, das verschwenderisch erscheint. Gibt es ein FragmentPagerAdapter
Äquivalent zu dem convertView
in listAdapter
, mit dem ich bereits erstellte Fragmente wiederverwenden kann? Mein Code ist unten.
public class ProfilePagerAdapter extends FragmentPagerAdapter {
ArrayList<Profile> mProfiles = new ArrayList<Profile>();
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));
}
}
onCreateView
Methode einzufügen, um zu sehen, wann jedes Fragment instanziiert wirdAnhang zu Geoffs Beitrag:
Sie können Bezug auf Ihre bekommen
Fragment
inFragmentPagerAdapter
VerwendungfindFragmentByTag()
. Der Name des Tags wird folgendermaßen generiert:private static String makeFragmentName(int viewId, int index) { return "android:switcher:" + viewId + ":" + index; }
Dabei ist viewId die ID von ViewPager
Schauen Sie sich diesen Link an: http://code.google.com/p/openintents/source/browse/trunk/compatibility/AndroidSupportV2/src/android/support/v2/app/FragmentPagerAdapter.java#104
quelle
getFragmentByPosition
. Wie ist die Position des Fragments?Fragments
erstellten speichernFragmentStatePagerAdapter
und diese verwenden, anstatt zu versuchen, sie mit zu findentags
(wasFragmentStatePagerAdapter
nicht verwendet wird).instantiateItem
IhreonCreate
wie hier beschrieben anrufenEs scheint, dass viele Leute, die diese Frage sehen, nach einer Möglichkeit suchen, auf das
Fragments
vonFragmentPagerAdapter
/ erstellte zu verweisenFragmentStatePagerAdapter
. Ich möchte meine Lösung dafür anbieten, ohne mich auf das intern Geschaffene zu verlassentags
, die die anderen Antworten hier verwenden.Als Bonus sollte diese Methode auch funktionieren
FragmentStatePagerAdapter
. Weitere Informationen finden Sie in den nachstehenden Hinweisen.Problem mit aktuellen Lösungen: Verlassen Sie sich auf internen Code
Viele der Lösungen, die ich für diese und ähnliche Fragen gesehen habe, basieren darauf, einen Verweis auf das Vorhandene zu erhalten
Fragment
,FragmentManager.findFragmentByTag()
indem das intern erstellte Tag"android:switcher:" + viewId + ":" + id
aufgerufen und nachgeahmt wird : . Das Problem dabei ist, dass Sie sich auf internen Quellcode verlassen, der bekanntlich nicht für immer gleich bleibt. Die Android-Ingenieure bei Google könnten leicht entscheiden, dietag
Struktur zu ändern, die Ihren Code beschädigen würde, sodass Sie keinen Verweis auf den vorhandenen finden könnenFragments
.Alternative Lösung ohne interne
tag
Hier ist ein einfaches Beispiel dafür, wie Sie einen Verweis auf das
Fragments
zurückgegebene erhaltenFragmentPagerAdapter
, der nicht vom internen abhängttags
Menge auf demFragments
. Der Schlüssel besteht darininstantiateItem()
, Referenzen dort zu überschreiben und zu speichern, anstatt ingetItem()
.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 retrieved from the FragmentManger // and not here (i.e. 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(); } } }
oder wenn Sie arbeiten lieber mit
tags
statt Klasse Membervariablen / Verweis auf dieFragments
Sie kann auch den greifentags
Satz vonFragmentPagerAdapter
auf die gleiche Weise: HINWEIS: dies gilt nicht ,FragmentStatePagerAdapter
da es nicht gesetzt ist ,tags
wenn seine ErstellungFragments
.@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: String firstTag = createdFragment.getTag(); break; case 1: String secondTag = createdFragment.getTag(); break; } // ... save the tags somewhere so you can reference them later return createdFragment; }
Beachten Sie, dass diese Methode NICHT auf der Nachahmung des internen
tag
Satzes durch beruhtFragmentPagerAdapter
und stattdessen geeignete APIs zum Abrufen verwendet. Auf diese Weise sind Sie auch dann sicher, wenn dietag
Änderungen in zukünftigen Versionen von vorgenommenSupportLibrary
werden.Vergessen Sie nicht, dass das Design
Activity
, an demFragments
Sie arbeiten möchten , je nach Design möglicherweise noch vorhanden ist oder nicht. Sie müssen dies also berücksichtigennull
Überprüfungen durchführen, bevor Sie Ihre Referenzen verwenden.Wenn Sie stattdessen mit arbeiten
FragmentStatePagerAdapter
, möchten Sie keine harten Verweise auf Ihre behalten,Fragments
da Sie möglicherweise viele davon haben und harte Verweise sie unnötigerweise im Speicher behalten würden. Speichern Sie stattdessen dieFragment
Referenzen inWeakReference
Variablen anstelle von Standardreferenzen. So was:WeakReference<Fragment> m1stFragment = new WeakReference<Fragment>(createdFragment); // ...and access them like so Fragment firstFragment = m1stFragment.get(); if (firstFragment != null) { // reference hasn't been cleared yet; do work... }
quelle
m1stFragment = (FragmentA) createdFragment;
hat für mich funktioniert und ich denke, es ist die beste Lösung hier. Aus irgendeinem Grund hat die alternative StrategieString firstTag = createdFragment.getTag();
bei mir nicht funktioniert. Vielen Dank @Turbo, das hat mich gerettet.instantiateItem
zu speichern Referenzen , wie Sie sollen AnrufinstantiateItem
in IhremonCreate
so können Sie einen Verweis speichern , indem der Weg dorthin.Wenn sich das Fragment noch im Speicher befindet, können Sie es mit dieser Funktion finden.
public Fragment findFragmentByPosition(int position) { FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter(); return getSupportFragmentManager().findFragmentByTag( "android:switcher:" + getViewPager().getId() + ":" + fragmentPagerAdapter.getItemId(position)); }
Beispielcode für die v4-Support-API.
quelle
Für zukünftige Leser!
Wenn Sie Fragmente mit Viewpager wiederverwenden möchten, verwenden Sie am besten ViewPager 2 , da View Pager 2 RecyclerView verwendet.
quelle
Ich weiß, dass dies (theoretisch) keine Antwort auf die Frage ist, sondern ein anderer Ansatz.
Ich hatte ein Problem, bei dem ich die sichtbaren Fragmente aktualisieren musste. Was auch immer ich versuchte, scheiterte und kläglich scheiterte ...
Nachdem ich so viele verschiedene Dinge ausprobiert habe, habe ich dies endlich mit beendet
BroadCastReceiver
. Senden Sie einfach eine Sendung, wenn Sie etwas mit den sichtbaren Fragmenten tun müssen, und erfassen Sie sie im Fragment.Wenn Sie auch eine Antwort benötigen, können Sie diese auch per Broadcast senden.
Prost
quelle