Différence entre add (), replace () et addToBackStack ()

300

Quelle est la principale différence entre appeler ces méthodes:

fragmentTransaction.addToBackStack(name);
fragmentTransaction.replace(containerViewId, fragment, tag);
fragmentTransaction.add(containerViewId, fragment, tag);

Que signifie remplacer un fragment déjà existant, ajouter un fragment à l'état d'activité et ajouter une activité à la pile arrière?

Deuxièmement, avec findFragmentByTag(), cette recherche de balise est-elle ajoutée par la méthode add()/ replace()ou la addToBackStack()méthode?

AndroidDev
la source

Réponses:

331

1) fragmentTransaction.addToBackStack(str);

Description - Ajouter cette transaction à la pile de retour. Cela signifie que la transaction sera mémorisée après avoir été validée et inversera son fonctionnement lorsqu'elle sera ultérieurement retirée de la pile.

2) fragmentTransaction.replace(int containerViewId, Fragment fragment, String tag)

Description - Remplacez un fragment existant qui a été ajouté à un conteneur. C'est essentiellement la même chose que d'appeler remove (Fragment) pour tous les fragments actuellement ajoutés qui ont été ajoutés avec le même containerViewId, puis add (int, Fragment, String) avec les mêmes arguments donnés ici.

3) fragmentTransaction.add(int containerViewId, Fragment fragment, String tag)

Description - Ajoutez un fragment à l'état d'activité. Ce fragment peut éventuellement également avoir sa vue (si Fragment.onCreateView retourne non null) dans une vue conteneur de l'activité.

Que signifie remplacer un fragment déjà existant, ajouter un fragment à l'état d'activité et ajouter une activité à la pile arrière?

Il existe une pile dans laquelle toutes les activités en cours d'exécution sont conservées. Les fragments appartiennent à l'activité. Vous pouvez donc les ajouter pour les intégrer dans une activité.

Vous pouvez combiner plusieurs fragments dans une seule activité pour créer une interface utilisateur à volets multiples et réutiliser un fragment dans plusieurs activités. Ceci est essentiellement utile lorsque vous avez défini votre conteneur de fragments dans différentes dispositions. Vous avez juste besoin de le remplacer par n'importe quel autre fragment dans n'importe quelle mise en page.

Lorsque vous accédez à la disposition actuelle, vous disposez de l'ID de ce conteneur pour le remplacer par le fragment souhaité.

Vous pouvez également revenir au fragment précédent dans le backStack avec la popBackStack()méthode. Pour cela, vous devez ajouter ce fragment dans la pile en utilisant addToBackStack()puis commit()réfléchir. C'est dans l'ordre inverse avec le courant en haut.

findFragmentByTag recherche-t-elle la balise ajoutée par la méthode add / replace ou la méthode addToBackStack?

Cela dépend de la façon dont vous avez ajouté la balise. Il trouve ensuite juste un fragment par sa balise que vous avez défini avant, soit lorsqu'il est gonflé à partir de XML ou tel qu'il est fourni lorsqu'il est ajouté dans une transaction.

Références: FragmentTransaction

Mon Dieu
la source
2
Alors, puis-je ajouter un fragment en remplaçant la méthode au début de l'activité lancée?
Yohanes AI
(Aucun fragment n'a été ajouté auparavant)
Yohanes AI
2
Un conteneur de fragments peut-il contenir plusieurs fragments? Si oui, comment la méthode replace () se comportera. WIll it replace all the frgaments in that container or android api have a method that accept three arguments, ie frgamentContainer, new fragment and with which to replace.
ved
1
@ved Non, il remplacera tous les fragments existant actuellement dans le conteneur par celui en cours.
reubenjohn
330

Une autre différence importante entre addet replaceest la suivante:

replacesupprime le fragment existant et ajoute un nouveau fragment. Cela signifie que lorsque vous appuyez sur le bouton de retour, le fragment qui a été remplacé sera créé avec son onCreateViewinvocation. Considérant que addconserve les fragments existants et ajoute un nouveau fragment qui signifie que le fragment existant sera actif et qu'ils ne seront pas en état de «pause», donc quand un bouton de retour est enfoncé, onCreateViewle fragment existant n'est pas appelé (le fragment qui était là avant que le nouveau fragment ne soit ajoutée).

En ce qui concerne les événements du cycle de vie du fragment onPause, onResume, onCreateViewet d' autres événements du cycle de vie seront invoquées en cas de replacemais ils ne seront pas invoquées en cas de add.

Edit : Il faut être prudent si elle utilise une sorte de bibliothèque de bus d'événements comme l' Eventbus de Greenrobot et réutilise le même fragment pour empiler le fragment sur un autre via add. Dans ce scénario, même si vous suivez la meilleure pratique et enregistrez onResumeet désinscrivez le onPausebus d'événements, le bus d'événements sera toujours actif dans chaque instance du fragment ajouté car le addfragment n'appellera pas l'une de ces méthodes de cycle de vie de fragment. En conséquence, l'écouteur de bus d'événements dans chaque instance active du fragment traiterait le même événement qui peut ne pas être ce que vous voulez.

Jeevan
la source
1
Je pense qu'une approche pourrait être de traiter l'événement dans le fragment le plus haut et d'appeler cancelEventDelivery () une fois le traitement terminé. Vous pouvez en savoir plus sur les méthodes cancelEventDelivery () ici github.com/greenrobot/EventBus/blob/master/…
Jeevan
6
+1 de moi. Très important de savoir que le remplacement du fragment actuel par un nouveau fragment signifie que le fragment précédent sera recréé pour le récupérer lors du retour de la pile de fragments.
AndaluZ
onPause, onResume est étroitement associé à l'activité de l'hôte. Et ils n'ont pas appelé lors du remplacement du fragment.
Zar E Ahmer
Juste pour ajouter à cela, si vous utilisez EventBus, vous pouvez ajouter le fragment avec Tag, et passer du fragment de cette balise à l'événement, et vérifier de toute façon, tous les bus d'événements seront appelés, vous spécifiez simplement celui qui doit être exécuté
user2582318
Vous devez mentionner que vous appelez addToBackStack () avec les méthodes add () ou replace ().
rahil008
100

Exemple une activité a 2 fragments et nous utilisons FragmentManagerpour remplacer / ajouter avec addToBackstackchaque fragment à une mise en page en activité

Utiliser remplacer

Go Fragment1

Fragment1: onAttach
Fragment1: onCreate
Fragment1: onCreateView
Fragment1: onActivityCreated
Fragment1: onStart
Fragment1: onResume

Go Fragment2

Fragment2: onAttach
Fragment2: onCreate
Fragment1: onPause
Fragment1: onStop
Fragment1: onDestroyView
Fragment2: onCreateView
Fragment2: onActivityCreated
Fragment2: onStart
Fragment2: onResume

Fragment Pop2

Fragment2: onPause
Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy
Fragment2: onDetach
Fragment1: onCreateView
Fragment1: onStart
Fragment1: onResume

Fragment Pop1

Fragment1: onPause
Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach

Utiliser ajouter

Go Fragment1

Fragment1: onAttach
Fragment1: onCreate
Fragment1: onCreateView
Fragment1: onActivityCreated
Fragment1: onStart
Fragment1: onResume

Go Fragment2

Fragment2: onAttach
Fragment2: onCreate
Fragment2: onCreateView
Fragment2: onActivityCreated
Fragment2: onStart
Fragment2: onResume

Fragment Pop2

Fragment2: onPause
Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy
Fragment2: onDetach

Fragment Pop1

Fragment1: onPause
Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach

Exemple de projet

Phan Van Linh
la source
1
n'était pas onPause()censé être appelé avant onStop()à chaque action Pop ?
iCantC
excellente réponse pour faire la différence entre 'add ()' et 'replace ()', bien que manquant sur addToBackStack (). Upvote
Shirish Herwade
@ShirishHerwade Je crois qu'il a démontré la différence entre ajouter et remplacer par addToBackStack dans les deux cas.
CyberShark
38

Bien qu'il s'agisse d'une vieille question à laquelle on a déjà répondu, peut-être que les prochains exemples peuvent compléter la réponse acceptée et peuvent être utiles pour certains nouveaux programmeurs sous Android comme je le suis.

Option 1 - "addToBackStack ()" n'est jamais utilisé

Cas 1A - ajouter, supprimer et cliquer sur le bouton Retour

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
add Fragment C :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment B is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               App is closed, nothing is visible

Cas 1B - ajouter, remplacer et cliquer sur le bouton Retour

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
(replace Fragment C)    
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()
Fragment C :        onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               App is closed, nothing is visible

Option 2 - "addToBackStack ()" est toujours utilisé

Cas 2A - ajouter, supprimer et cliquer sur le bouton Retour

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
add Fragment C :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView()                              Fragment B is visible
(Back button clicked)
Fragment C :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment C is visible
(Back button clicked)
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment B is visible
(Back button clicked)
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment A is visible
(Back button clicked)
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible

Cas 2B - ajouter, remplacer, supprimer et cliquer sur le bouton Retour

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
(replace Fragment C)    
Fragment B :        onPause() - onStop() - onDestroyView()  
Fragment A :        onPause() - onStop() - onDestroyView() 
Fragment C :        onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView()                              Activity is visible
(Back button clicked)
Fragment C :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment C is visible
(Back button clicked)
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onCreateView() - onActivityCreated() - onStart() - onResume()   
Fragment B :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment B is visible
(Back button clicked)
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment A is visible
(Back button clicked)
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible

Option 3 - "addToBackStack ()" n'est pas toujours utilisé (dans les exemples ci-dessous, w / o indique qu'il n'est pas utilisé)

Cas 3A - ajouter, supprimer et cliquer sur le bouton Retour

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B w/o:     onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
add Fragment C w/o:     onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment B is visible
(Back button clicked)
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible

Cas 3B - ajouter, remplacer, supprimer et cliquer sur le bouton Retour

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B w/o:     onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
(replace Fragment C)    
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()   
Fragment A :        onPause() - onStop() - onDestroyView() 
Fragment C :        onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView()                              Activity is visible
(Back button clicked)
Fragment C :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment C is visible
(Back button clicked)
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment A is visible
(Back button clicked)
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible
Javi
la source
1
Assez bien. Bon effort!
pulp_fiction
Alors, pouvons-nous dire que tout en travaillant avec des fragments, le bouton de retour fonctionne de la même manière que la fonction FragmentManager.popBackStack ()?
Tintin
grande réponse, ne peut pas être mieux. Cette réponse devrait être acceptée.
Shirish Herwade
25

La différence fondamentale entre add()et replace()peut être décrite comme:

  • add() est utilisé pour simplement ajouter un fragment à un élément racine.
  • replace() se comporte de la même façon, mais au début, il supprime les fragments précédents, puis ajoute le fragment suivant.

Nous pouvons voir la différence exacte lorsque nous utilisons addToBackStack()avec add()ou replace().

Lorsque nous add()appuyons sur le bouton de retour après en cas de ... onCreateView n'est jamais appelé, mais en cas de replace(), lorsque nous appuyons sur le bouton de retour ... oncreateView est appelé à chaque fois.

Avanindra_dubey
la source
1
Est-ce que add () entraîne plus de charge en termes de mémoire Android, car la vue du fragment précédent n'est pas détruite?
Derekyy
@Derekyy Oui, je pense que oui.
Arpit J.
est ce que je cherchais
parvez rafi
2

Lorsque nous ajoutons le premier fragment -> Deuxième fragment à l'aide de la méthode add ()

 btn_one.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(),"Click First 
Fragment",Toast.LENGTH_LONG).show();

                Fragment fragment = new SecondFragment();
                getActivity().getSupportFragmentManager().beginTransaction()
                        .add(R.id.fragment_frame, fragment, fragment.getClass().getSimpleName()).addToBackStack(null).commit();
//                        .replace(R.id.fragment_frame, fragment, fragment.getClass().getSimpleName()).addToBackStack(null).commit();

            }
        });

Lorsque nous utilisons add () dans un fragment

E/Keshav SecondFragment: onAttach
E/Keshav SecondFragment: onCreate
E/Keshav SecondFragment: onCreateView
E/Keshav SecondFragment: onActivityCreated
E/Keshav SecondFragment: onStart
E/Keshav SecondFragment: onResume

Lorsque nous utilisons replace () dans un fragment

aller du premier fragment au deuxième fragment dans First -> Second en utilisant la méthode replace ()

 btn_one.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(),"Click First Fragment",Toast.LENGTH_LONG).show();

                Fragment fragment = new SecondFragment();
                getActivity().getSupportFragmentManager().beginTransaction()
//                        .add(R.id.fragment_frame, fragment, fragment.getClass().getSimpleName()).addToBackStack(null).commit();
                        .replace(R.id.fragment_frame, fragment, fragment.getClass().getSimpleName()).addToBackStack(null).commit();

            }
        });

E/Keshav SecondFragment: onAttach
E/Keshav SecondFragment: onCreate

E/Keshav FirstFragment: onPause -------------------------- FirstFragment
E/Keshav FirstFragment: onStop --------------------------- FirstFragment
E/Keshav FirstFragment: onDestroyView -------------------- FirstFragment

E/Keshav SecondFragment: onCreateView
E/Keshav SecondFragment: onActivityCreated
E/Keshav SecondFragment: onStart
E/Keshav SecondFragment: onResume

En cas de remplacement du premier fragment, cette méthode est appelée de manière supplémentaire (onPause, onStop, onDestroyView est appelé de manière supplémentaire)

E / Keshav FirstFragment: onPause

E / Keshav FirstFragment: onStop

E / Keshav FirstFragment: onDestroyView

Keshav Gera
la source
0

Les fonctions d'ajout et de remplacement de FragmentManger peuvent être décrites comme suit: 1. ajouter signifie qu'il ajoutera le fragment dans la pile arrière de fragments et qu'il s'affichera à l'image donnée que vous fournissez comme

getFragmentManager.beginTransaction.add(R.id.contentframe,Fragment1.newInstance(),null)

2. remplacer signifie que vous remplacez le fragment par un autre fragment à la trame donnée

getFragmentManager.beginTransaction.replace(R.id.contentframe,Fragment1.newInstance(),null)

L'utilitaire principal entre les deux est que lorsque vous empilerez à nouveau, le remplacement rafraîchira le fragment mais l'ajout ne rafraîchira pas le fragment précédent.

raj kavadia
la source
0

Chose importante à noter:

La différence entre Remplacer et Remplacer par backstack est chaque fois que nous utilisons uniquement replace alors le fragment est détruit (ondestroy () est appelé) et lorsque nous utilisons replace with backstack alors les fragments onDestroy () ne sont pas appelés (c'est-à-dire lorsque le bouton Retour est enfoncé, le fragment est appelé avec son onCreateView ())

Lloyd Dcosta
la source
0

Voici une image qui montre la différence entre add()etreplace()

entrez la description de l'image ici

Ainsi, la add()méthode continue d'ajouter des fragments au-dessus du fragment précédent dans FragmentContainer.

Alors que les replace()méthodes effacent tous les fragments précédents des conteneurs, puis les ajoutent dans FragmentContainer.

Qu'est-ce que addToBackStack

addtoBackStackLa méthode peut être utilisée avec les méthodes add () et replace. Il sert un objectif différent dans l'API Fragment.

Quel est le but?

L'API de fragmentation contrairement à l'API d'activité n'est pas fournie par défaut avec la navigation du bouton Retour . Si vous souhaitez revenir au fragment précédent, la méthode we use addToBackStack () dans Fragment. Comprenons les deux

Cas 1:

getSupportFragmentManager()
            .beginTransaction()
            .add(R.id.fragmentContainer, fragment, "TAG")
            .addToBackStack("TAG")
            .commit();

entrez la description de l'image ici

Cas 2:

getSupportFragmentManager()
            .beginTransaction()
            .add(R.id.fragmentContainer, fragment, "TAG")
            .commit();

entrez la description de l'image ici

Rohit Singh
la source