Navigieren Sie zurück zu FragmentPagerAdapter -> Fragmente sind leer

Lesezeit: 5 Minuten

Benutzer-Avatar
Amit Ishai

Ich habe ein Fragment (ich nenne es pagerFragment), die dem Backstack hinzugefügt wird und sichtbar ist. Es hält a viewPager mit einer FragmentPagerAdapter. Das FragmentPagerAdapter enthält (sagen wir) zwei Fragmente: A und B.

Das erste Hinzufügen der Fragmente funktioniert super.

Fragment A hat eine Schaltfläche, die nach dem Klicken ein Fragment (C) zum Backstack hinzufügt.

Das Problem ist folgendes: Wenn ich dieses Fragment (C) hinzufüge und dann zurückklicke, wird die pagerAdapter ist leer, und ich kann keine Fragmente darin sehen.

Wenn ich einen Hack verwende, zerstöre ich die Kinderfragmente (A und B) in der pagerFragments onDestroyView()das löst das Problem, obwohl ich diesen Hack nicht verwenden möchte.

Irgendwelche Ideen, was das Problem sein könnte?

  • Ein mögliches Duplikat von Fragment in ViewPager mit FragmentPagerAdapter ist bei der zweiten Anzeige leer

    – bladibla

    16. Juni 2016 um 23:42 Uhr

Ich hatte das gleiche Problem. Die Lösung war für mich einfach:

in onCreateView hatte ich:

// Create the adapter that will return a fragment for each of the three
// primary sections of the app.
mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity()
    .getSupportFragmentManager());

wo SectionPageAdapter so etwas ist:

class SectionsPagerAdapter extends FragmentPagerAdapter {
...
}

nach dem Ändern von getSupportFragmentManager zu

mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());

es hat funktioniert! Hoffe das hilft.

  • getChildFragmentManager() funktioniert nur mit 17+ Android SDK. 🙁

    – Sachin Schelke

    10. März 2014 um 15:52 Uhr

  • @SachinShelke Sie müssen dann die Support-Bibliothek verwenden. 😉 developer.android.com/reference/android/support/v4/app/…

    – Sufian

    5. Juni 2014 um 13:50 Uhr

  • @mike-mitterer, erstaunliche Antwort, du bist großartig, vielen Dank

    – Tom

    28. Juli 2014 um 20:53 Uhr

  • Guter Gott, ich habe 3 Stunden mit diesem Problem verbracht. Dieser Fix hat einwandfrei funktioniert. Ich habe nur ein paar Stunden verloren, die ich nie wieder sehen werde. fml

    – Laith Alnagem

    29. Januar 2015 um 3:16 Uhr

  • Kann jemand erklären warum getSupportFragmentManager() geht nicht, aber getChildFragmentManager() funktioniert? Wie sind die Ansichten nested beim Zurückdrücken? Gibt es eine Nebenwirkung dazu?

    – aandis

    4. April 2015 um 7:19 Uhr


Benutzer-Avatar
Pierre-Antoine LaFayette

Es hört sich so an, als würden Sie verschachtelte Fragmente verwenden, da sich Ihr ViewPager in einem PagerFragment befindet. Haben Sie getChildFragmentManager() an den Konstruktor Ihres FragmentPagerAdapter übergeben? Wenn nicht, sollten Sie.

Ich glaube nicht, dass Sie einen FragmentStatePagerAdapter benötigen, aber ich würde dem eine Chance geben, da er das Speichern und Wiederherstellen des Fragmentstatus übernimmt. Die Tatsache, dass Ihr onDestroyView()-Hack funktioniert, lässt mich denken, dass Sie vielleicht einen FragmentStatePagerAdapter wollen.

Es könnte auch etwas damit zu tun haben, wie der FragmentPagerAdapter Fragmente hinzufügt. Der FragmentPagerAdapter fügt dem Backstack keine Fragmente hinzu. Stellen Sie sich vor, Sie hätten mehr als 10 Seiten in Ihrem ViewPager hinzugefügt und der Benutzer wischte durch sie hindurch. Der Benutzer müsste 11 Mal zurückschlagen, um die App zu verlassen.

Es kann auch mit diesem Beitrag zusammenhängen: Verschachtelte Fragmente und The Back Stack.

Ich bin mir auch nicht sicher, wozu Sie das Fragment C hinzufügen. Fügen Sie es demselben Container wie ViewPager hinzu?

Nun, zumindest haben Sie ein paar Möglichkeiten, dies zu untersuchen. In diesen Situationen debugge ich gerne den Android SDK-Quellcode und sehe, was das Verhalten verursacht. Ich empfehle, die zu greifen AOSP-Quelle und Hinzufügen von frameworks/support und frameworks/base als SDK-Quellen. Das ist der einzig wahre Weg, um zu verstehen, was passiert, und willkürliche Änderungen zu vermeiden, bis die Dinge funktionieren.

Verwenden getChildFragmentManager() Anstatt von getSupportFragmentManager(). Es wird gut funktionieren.

Ich stand gerade auch vor dem Problem in unserem Projekt. Die Hauptursache ist die Funktionsweise des FragmentPagerAdapter:

Der FragmentPagerAdapter trennt lediglich ein Fragment, das er derzeit nicht benötigt, aus seiner Ansicht, entfernt es jedoch nicht aus seinem FragmentManager. Wenn er das Fragment erneut anzeigen möchte, prüft er, ob der FragmentManager das Fragment noch enthält, indem er ein Tag verwendet, das aus der Ansichts-ID des ViewPagers und der vom getItemId(position)-Aufruf des Adapters zurückgegebenen ID erstellt wird. Wenn er ein Fragment findet, plant er einfach ein Anhängen des Fragments an seine Ansicht innerhalb der Aktualisierungstransaktion des FragmentManagers. Nur wenn er auf diese Weise kein Fragment findet, erstellt er ein neues mit dem getItem(position)-Aufruf des Adapters!

Das Problem bei einem Fragment, das einen ViewPager mit einem FragmentPagerAdapter enthält, besteht darin, dass der Inhalt des FragmentManagers niemals bereinigt wird, wenn das enthaltende Fragment auf den Backstack gelegt wird. Wenn das enthaltende Fragment aus dem Backstack zurückkommt, erstellt es eine neue Ansicht, aber der FragmentManager enthält immer noch die Fragmente, die an die alte Ansicht angehängt waren, und das Anhängen eines vorhandenen Fragments funktioniert nicht mehr.

Der einfachste Weg, dieses Problem zu beseitigen, besteht darin, verschachtelte Fragmente zu vermeiden. 🙂

Der zweiteinfachste Weg ist, wie bereits in anderen Beiträgen erwähnt, den ChildFragmentManager für den FragmentPagerAdapter zu verwenden, da dieser während des Lebenszyklus des Containerfragments ordnungsgemäß aktualisiert wird.

Da es Projekte gibt (wie mein aktuelles), bei denen beide Optionen nicht möglich sind, habe ich hier eine Lösung veröffentlicht, die mit einem beliebigen FragmentManager funktioniert, indem der HashCode der Unterfragmente als Element-ID des Fragments an dieser Position verwendet wird. Dies hat den Preis, dass alle Fragmente für alle Positionen innerhalb des Adapters gespeichert werden.

public class MyPagerAdapter extends FragmentPagerAdapter {

private static int COUNT = ...;
private final FragmentManager fragmentManager;
private Fragment[] subFragments = new Fragment[COUNT];
private FragmentTransaction cleanupTransaction;

public MyPagerAdapter(FragmentManager fragmentManager) {
    super(fragmentManager);
    this.fragmentManager = fragmentManager;
}

@Override
public Fragment getItem(int position) {
    return getSubFragmentAtPosition(position);
}

@Override
public int getCount() {
    return COUNT;
}

@Override
public long getItemId(int position) {
    return getSubFragmentAtPosition(position).hashCode();
}

//The next three methods are needed to remove fragments no longer used from the fragment manager
@Override
public void startUpdate(ViewGroup container) {
    super.startUpdate(container);
    cleanupTransaction = fragmentManager.beginTransaction();
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    super.destroyItem(container, position, object);
    cleanupTransaction.remove((Fragment) object);
}

@Override
public void finishUpdate(ViewGroup container) {
    super.finishUpdate(container);
    cleanupTransaction.commit();
}

private Fragment getSubFragmentAtPosition(int position){
    if (subFragments[position] == null){
        subFragments[position] = ...;
    }
    return subFragments[position];
}

}

Ich hatte das gleiche Problem, Adapter einfach zweimal auf einmal einstellen und das war’s.

Beispielcode:

private fun displayImg(photo1:String, photo2:String){
    val pager:ViewPager = v?.findViewById(R.id.ProductImgPager)!!
    val arr = ArrayList<String>()
    arr.add(photo1)
    arr.add(photo2)
    pager.adapter = AdapterImageView(fm, arr ,arr.size)
    pager.adapter = AdapterImageView(fm, arr ,arr.size)

}

1180020cookie-checkNavigieren Sie zurück zu FragmentPagerAdapter -> Fragmente sind leer

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy