Transactions de fragment

Au moment de l'exécution, un objet FragmentManager peut ajouter, supprimer, remplacer et effectuer d'autres actions avec des fragments en réponse à une interaction avec l'utilisateur. Chaque ensemble de modifications de fragment que vous validez est appelé transaction. Vous pouvez spécifier ce qu'il faut faire à l'intérieur de la transaction à l'aide des API fournies par la classe FragmentTransaction. Vous pouvez regrouper plusieurs actions dans une seule transaction. Par exemple, une transaction peut ajouter ou remplacer plusieurs fragments. Ce regroupement peut être utile lorsque plusieurs fragments frères sont affichés sur le même écran, par exemple avec des affichages fractionnés.

Vous pouvez enregistrer chaque transaction dans une pile "Retour" gérée par FragmentManager, ce qui permet à l'utilisateur de faire défiler les modifications de fragment en arrière, comme il est possible de le faire pour les activités.

Vous pouvez obtenir une instance de FragmentTransaction à partir de FragmentManager en appelant beginTransaction(), comme illustré dans l'exemple suivant :

Kotlin

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

Java

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

Le dernier appel sur chaque FragmentTransaction doit valider la transaction. L'appel commit() indique à FragmentManager que toutes les opérations ont été ajoutées à la transaction.

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();

Autoriser la réorganisation des modifications d'état de fragment

Chaque FragmentTransaction doit utiliser setReorderingAllowed(true) :

Kotlin

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

Java

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

Pour des raisons de compatibilité de comportements, l'indicateur de réorganisation n'est pas activé par défaut. Il est toutefois nécessaire d'autoriser FragmentManager à exécuter correctement FragmentTransaction, en particulier lorsqu'il fonctionne sur la pile "Retour" et qu'il exécute des animations et des transitions. L'activation de cet indicateur garantit que si plusieurs transactions sont exécutées ensemble, les fragments intermédiaires (c'est-à-dire ceux qui sont ajoutés puis remplacés immédiatement) ne subissent pas de modifications du cycle de vie, et leurs animations ou transitions ne sont pas exécutées. Notez que cet indicateur affecte à la fois l'exécution initiale de la transaction et l'annulation de la transaction avec popBackStack().

Ajouter et supprimer des fragments

Pour ajouter un fragment à un FragmentManager, appelez add() sur la transaction. Cette méthode reçoit l'identifiant du conteneur pour le fragment, ainsi que le nom de classe du fragment que vous souhaitez ajouter. Le fragment ajouté passe à l'état RESUMED. Il est vivement recommandé que le conteneur soit un FragmentContainerView faisant partie de la hiérarchie des affichages.

Pour supprimer un fragment de l'hôte, appelez remove() en transmettant une instance de fragment récupérée du gestionnaire de fragments via findFragmentById() ou findFragmentByTag(). Si l'affichage du fragment a déjà été ajouté à un conteneur, l'affichage est alors supprimé du conteneur à ce stade. Le fragment supprimé passe à l'état DESTROYED.

Utilisez replace() pour remplacer un fragment existant dans un conteneur par une instance de la nouvelle classe de fragment que vous fournissez. L'appel de replace() équivaut à appeler remove() avec un fragment dans un conteneur et à ajouter un fragment à ce même conteneur.

L'extrait de code suivant montre comment remplacer un fragment par un autre :

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();

Dans cet exemple, une nouvelle instance de ExampleFragment remplace, le cas échéant, le fragment qui se trouve actuellement dans le conteneur de mise en page identifié par R.id.fragment_container.

Par défaut, les modifications apportées à une FragmentTransaction ne sont pas ajoutées à la pile "Retour". Pour enregistrer ces modifications, vous pouvez appeler addToBackStack() sur la FragmentTransaction. Pour en savoir plus, consultez la page Gestionnaire de fragments.

Le commit est asynchrone

L'appel de commit() ne permet pas d'effectuer la transaction immédiatement. La transaction est programmée pour s'exécuter sur le thread UI principal dès qu'elle le peut. Toutefois, si nécessaire, vous pouvez appeler commitNow() pour exécuter immédiatement la transaction de fragment sur votre thread UI.

Notez que commitNow n'est pas compatible avec addToBackStack. Sinon, vous pouvez exécuter toutes les FragmentTransactions en attente envoyées par des appels commit() qui ne sont pas encore exécutées en appelant executePendingTransactions(). Cette approche est compatible avec addToBackStack.

Pour la grande majorité des cas d'utilisation, commit() suffit.

L'ordre des opérations est important

L'ordre dans lequel vous effectuez les opérations dans un FragmentTransaction est important, en particulier lorsque vous utilisez setCustomAnimations(). Cette méthode applique les animations données à toutes les opérations de fragment qui le suivent.

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()

Limiter le cycle de vie du fragment

FragmentTransactions peut affecter l'état du cycle de vie des fragments individuels ajoutés dans le champ d'application de la transaction. Lors de la création d'une FragmentTransaction, setMaxLifecycle() définit un état maximal pour le fragment donné. Par exemple, ViewPager2 utilise setMaxLifecycle() pour limiter les fragments hors écran à l'état STARTED.

Afficher et masquer les affichages de fragment

Utilisez les méthodes show() et hide() de FragmentTransaction pour afficher et masquer l'affichage des fragments qui ont été ajoutés à un conteneur. Ces méthodes définissent la visibilité des affichages du fragment sans affecter le cycle de vie du fragment.

Bien qu'il ne soit pas nécessaire d'utiliser une transaction de fragment pour activer ou désactiver la visibilité des affichages dans un fragment, ces méthodes sont utiles dans les cas où vous souhaitez associer les modifications de l'état de visibilité aux transactions dans la pile "Retour".

Associer et dissocier des fragments

La méthode detach() de FragmentTransaction dissocie le fragment de l'interface utilisateur, et détruit ainsi la hiérarchie des affichages. Le fragment reste dans le même état (STOPPED) que lorsqu'il est placé sur la pile "Retour". Cela signifie que le fragment a été supprimé de l'interface utilisateur, mais qu'il est toujours géré par le gestionnaire de fragments.

La méthode attach() associe à nouveau un fragment dont il a été précédemment dissocié. Ainsi, la hiérarchie des affichages est recréée, associée à l'interface utilisateur et affichée.

Étant donné qu'une FragmentTransaction est traitée comme un ensemble atomique unique d'opérations, les appels detach et attach sur la même instance de fragment dans la même transaction s'annulent mutuellement, et permet ainsi d'éviter la destruction et la recréation immédiate de l'interface utilisateur du fragment. Si vous souhaitez dissocier puis réassocier immédiatement un fragment, utilisez des transactions distinctes séparées par executePendingOperations() si vous utilisez commit().