Fragment-Transaktionen

Zur Laufzeit können mit einem FragmentManager als Reaktion auf Nutzerinteraktionen andere Aktionen mit Fragmenten hinzugefügt, entfernt, ersetzt und ausgeführt werden. Jede Gruppe von Fragmentänderungen, für die Sie einen Commit durchführen, wird als Transaktion bezeichnet. Mit den von der Klasse FragmentTransaction bereitgestellten APIs können Sie angeben, was innerhalb der Transaktion passieren soll. Sie können mehrere Aktionen in einer einzigen Transaktion gruppieren. Eine Transaktion kann beispielsweise mehrere Fragmente hinzufügen oder ersetzen. Diese Gruppierung kann nützlich sein, wenn mehrere gleichgeordnete Fragmente auf demselben Bildschirm angezeigt werden, z. B. bei geteilten Ansichten.

Sie können jede Transaktion in einem Back-Stack speichern, der von FragmentManager verwaltet wird. So kann der Nutzer rückwärts durch die Fragmentänderungen navigieren, ähnlich wie beim Zurückgehen durch Aktivitäten.

Sie können eine Instanz von FragmentTransaction aus FragmentManager abrufen, indem Sie beginTransaction() wie im folgenden Beispiel aufrufen:

Kotlin

val fragmentManager = ...
val fragmentTransaction = fragmentManager.beginTransaction()

Java

FragmentManager fragmentManager = ...
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

Der letzte Aufruf an jeder FragmentTransaction muss die Transaktion mit Commit durchführen. Der commit()-Aufruf signalisiert der FragmentManager, dass alle Vorgänge der Transaktion hinzugefügt wurden.

Kotlin

val fragmentManager = ...
// The fragment-ktx module provides a commit block that automatically
// calls beginTransaction and commit for you.
fragmentManager.commit {
    // Add operations here
}

Java

FragmentManager fragmentManager = ...
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

// Add operations here

fragmentTransaction.commit();

Neuanordnung von Änderungen des Fragmentstatus zulassen

Für jeden FragmentTransaction sollte setReorderingAllowed(true) verwendet werden:

Kotlin

supportFragmentManager.commit {
    ...
    setReorderingAllowed(true)
}

Java

FragmentManager fragmentManager = ...
fragmentManager.beginTransaction()
    ...
    .setReorderingAllowed(true)
    .commit();

Aus Gründen der Verhaltenskompatibilität ist das Flag für die Neuanordnung nicht standardmäßig aktiviert. Sie müssen jedoch zulassen, dass FragmentManager Ihre FragmentTransaction ordnungsgemäß ausführen kann, insbesondere wenn sie auf dem Back-Stack ausgeführt wird und Animationen und Übergänge ausführt. Durch Aktivieren des Flags wird bei der gemeinsamen Ausführung mehrerer Transaktionen sichergestellt, dass Zwischenfragmente (d.h. solche, die hinzugefügt und dann sofort ersetzt werden) keine Lebenszyklusänderungen durchlaufen oder deren Animationen oder Übergänge ausgeführt werden. Dieses Flag wirkt sich sowohl auf die erste Ausführung der Transaktion als auch auf das Umkehren der Transaktion mit popBackStack() aus.

Fragmente hinzufügen und entfernen

Wenn Sie einem FragmentManager ein Fragment hinzufügen möchten, rufen Sie für die Transaktion add() auf. Diese Methode empfängt die ID des Containers für das Fragment sowie den Klassennamen des Fragments, das Sie hinzufügen möchten. Das hinzugefügte Fragment wird in den Status RESUMED verschoben. Es wird dringend empfohlen, dass der Container eine FragmentContainerView ist, die Teil der Ansichtshierarchie ist.

Um ein Fragment vom Host zu entfernen, rufen Sie remove() auf und übergeben Sie eine Fragmentinstanz, die über findFragmentById() oder findFragmentByTag() aus dem Fragmentmanager abgerufen wurde. Wenn die Ansicht des Fragments bereits einem Container hinzugefügt wurde, wird die Ansicht an dieser Stelle aus dem Container entfernt. Das entfernte Fragment wird in den Status DESTROYED verschoben.

Mit replace() können Sie ein vorhandenes Fragment in einem Container durch die Instanz einer neuen Fragmentklasse ersetzen, die Sie zur Verfügung stellen. Der Aufruf von replace() entspricht dem Aufruf von remove() mit einem Fragment in einem Container und dem Hinzufügen eines neuen Fragments zu demselben Container.

Das folgende Code-Snippet zeigt, wie Sie ein Fragment durch ein anderes ersetzen:

Kotlin

// Create new fragment
val fragmentManager = // ...

// Create and commit a new transaction
fragmentManager.commit {
    setReorderingAllowed(true)
    // Replace whatever is in the fragment_container view with this fragment
    replace<ExampleFragment>(R.id.fragment_container)
}

Java

// Create new fragment and transaction
FragmentManager fragmentManager = ...
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setReorderingAllowed(true);

// Replace whatever is in the fragment_container view with this fragment
transaction.replace(R.id.fragment_container, ExampleFragment.class, null);

// Commit the transaction
transaction.commit();

In diesem Beispiel wird das Fragment, das sich derzeit im durch R.id.fragment_container identifizierten Layout-Container befindet, durch eine neue Instanz von ExampleFragment ersetzt.

Standardmäßig werden die in einem FragmentTransaction vorgenommenen Änderungen nicht dem Back-Stack hinzugefügt. Um diese Änderungen zu speichern, können Sie im FragmentTransaction addToBackStack() aufrufen. Weitere Informationen finden Sie unter Fragmentmanager.

Commit ist asynchron

Durch das Aufrufen von commit() wird die Transaktion nicht sofort ausgeführt. Stattdessen wird die Transaktion so geplant, dass sie sobald wie möglich im Haupt-UI-Thread ausgeführt wird. Bei Bedarf können Sie jedoch commitNow() aufrufen, um die Fragmenttransaktion sofort in Ihrem UI-Thread auszuführen.

commitNow ist nicht mit addToBackStack kompatibel. Alternativ können Sie alle ausstehenden FragmentTransactions ausführen, die von commit()-Aufrufen gesendet wurden, die noch nicht ausgeführt wurden, indem Sie executePendingTransactions() aufrufen. Dieser Ansatz ist mit addToBackStack kompatibel.

Für die meisten Anwendungsfälle ist commit() alles, was Sie benötigen.

Die Reihenfolge der Vorgänge ist wichtig

Die Reihenfolge, in der Sie Vorgänge innerhalb einer FragmentTransaction ausführen, ist wichtig, insbesondere wenn Sie setCustomAnimations() verwenden. Bei dieser Methode werden die Animationen auf alle folgenden Fragmentvorgänge angewendet.

Kotlin

supportFragmentManager.commit {
    setCustomAnimations(enter1, exit1, popEnter1, popExit1)
    add<ExampleFragment>(R.id.container) // gets the first animations
    setCustomAnimations(enter2, exit2, popEnter2, popExit2)
    add<ExampleFragment>(R.id.container) // gets the second animations
}

Java

getSupportFragmentManager().beginTransaction()
        .setCustomAnimations(enter1, exit1, popEnter1, popExit1)
        .add(R.id.container, ExampleFragment.class, null) // gets the first animations
        .setCustomAnimations(enter2, exit2, popEnter2, popExit2)
        .add(R.id.container, ExampleFragment.class, null) // gets the second animations
        .commit()

Lebenszyklus des Fragments beschränken

FragmentTransactions kann den Lebenszyklusstatus einzelner Fragmente beeinflussen, die im Bereich der Transaktion hinzugefügt werden. Beim Erstellen eines FragmentTransaction legt setMaxLifecycle() einen Höchstzustand für das jeweilige Fragment fest. Beispielsweise verwendet ViewPager2 setMaxLifecycle(), um die Fragmente außerhalb des Bildschirms auf den Status STARTED zu beschränken.

Fragmentansichten anzeigen und ausblenden

Mit den FragmentTransaction-Methoden show() und hide() können Sie die Ansicht von Fragmenten ein- oder ausblenden, die einem Container hinzugefügt wurden. Mit diesen Methoden wird die Sichtbarkeit der Ansichten des Fragments festgelegt, ohne den Lebenszyklus des Fragments zu beeinträchtigen.

Sie müssen keine Fragment-Transaktion verwenden, um die Sichtbarkeit der Ansichten innerhalb eines Fragments umzuschalten. Diese Methoden sind jedoch nützlich, wenn Änderungen des Sichtbarkeitsstatus mit Transaktionen im Back-Stack verknüpft werden sollen.

Fragmente anhängen und trennen

Die FragmentTransaction-Methode detach() trennt das Fragment von der UI und zerstört die Ansichtshierarchie. Das Fragment bleibt im selben Zustand (STOPPED) wie beim Verschieben in den Back-Stack. Das bedeutet, dass das Fragment aus der UI entfernt wurde, aber weiterhin vom Fragmentmanager verwaltet wird.

Mit der Methode attach() wird ein Fragment, von dem es zuvor getrennt war, noch einmal angehängt. Dadurch wird die Ansichtshierarchie neu erstellt, an die UI angehängt und angezeigt.

Da ein FragmentTransaction als einzelner atomarer Satz von Vorgängen behandelt wird, heben sich Aufrufe von detach und attach für dieselbe Fragmentinstanz in derselben Transaktion gegenseitig auf. Dadurch wird das Zerstörung und die sofortige Wiederherstellung der UI des Fragments vermieden. Verwenden Sie separate Transaktionen, die durch executePendingOperations() getrennt sind, wenn Sie commit() verwenden, wenn Sie ein Fragment trennen und dann sofort wieder anhängen möchten.