Unterschied zwischen add (), replace () und addToBackStack ()

300

Was ist der Hauptunterschied zwischen dem Aufrufen dieser Methoden:

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

Was bedeutet es, ein bereits vorhandenes Fragment zu ersetzen, dem Aktivitätsstatus ein Fragment hinzuzufügen und dem Backstack eine Aktivität hinzuzufügen?

Zweitens, mit findFragmentByTag(), sucht diese Suche nach Tags, die von der add()/ replace()-Methode oder der addToBackStack()Methode hinzugefügt wurden ?

AndroidDev
quelle

Antworten:

331

1) fragmentTransaction.addToBackStack(str);

Beschreibung - Fügen Sie diese Transaktion dem Backstack hinzu. Dies bedeutet, dass die Transaktion nach dem Festschreiben gespeichert wird und ihren Vorgang umkehrt, wenn sie später vom Stapel entfernt wird.

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

Beschreibung - Ersetzen Sie ein vorhandenes Fragment, das einem Container hinzugefügt wurde. Dies entspricht im Wesentlichen dem Aufruf von remove (Fragment) für alle aktuell hinzugefügten Fragmente, die mit derselben containerViewId hinzugefügt wurden, und add (int, Fragment, String) mit denselben hier angegebenen Argumenten.

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

Beschreibung - Fügen Sie dem Aktivitätsstatus ein Fragment hinzu. Dieses Fragment kann optional auch seine Ansicht (wenn Fragment.onCreateView ungleich Null zurückgibt) in einer Containeransicht der Aktivität haben.

Was bedeutet es, ein bereits vorhandenes Fragment zu ersetzen, dem Aktivitätsstatus ein Fragment hinzuzufügen und dem Backstack eine Aktivität hinzuzufügen?

Es gibt einen Stapel, in dem alle Aktivitäten im laufenden Zustand gespeichert sind. Fragmente gehören zur Aktivität. Sie können sie also hinzufügen, um sie in eine Aktivität einzubetten.

Sie können mehrere Fragmente in einer einzigen Aktivität kombinieren, um eine Benutzeroberfläche mit mehreren Fenstern zu erstellen und ein Fragment in mehreren Aktivitäten wiederzuverwenden. Dies ist im Wesentlichen nützlich, wenn Sie Ihren Fragmentcontainer in verschiedenen Layouts definiert haben. Sie müssen nur durch ein anderes Fragment in einem beliebigen Layout ersetzen.

Wenn Sie zum aktuellen Layout navigieren, haben Sie die ID dieses Containers, um ihn durch das gewünschte Fragment zu ersetzen.

Sie können mit der popBackStack()Methode auch zum vorherigen Fragment im backStack zurückkehren . Dazu müssen Sie dieses Fragment mit addToBackStack()und dann commit()zum Reflektieren in den Stapel einfügen. Dies erfolgt in umgekehrter Reihenfolge, wobei der Strom oben liegt.

findFragmentByTag Sucht diese Suche nach Tags, die durch die Methode add / replace oder die Methode addToBackStack hinzugefügt wurden?

Ob hängt davon ab, wie Sie das Tag hinzugefügt haben. Es findet dann nur ein Fragment anhand seines Tags, das Sie zuvor definiert haben, entweder beim Aufblasen aus XML oder wie beim Hinzufügen in einer Transaktion angegeben.

Referenzen: FragmentTransaction

Mein Gott
quelle
2
Kann ich also zu Beginn der aktivierten Aktivität ein Fragment durch Ersetzen der Methode hinzufügen?
Yohanes AI
(Kein Fragment wurde zuvor hinzugefügt)
Yohanes AI
2
Kann ein Fragmentcontainer mehr als ein Fragment enthalten? Wenn ja, wie verhält sich die Methode replace ()? Wird es alle Frgamente in diesem Container oder Android API ersetzen, haben Sie eine Methode, die drei Argumente akzeptiert, dh FrgamentContainer, neues Fragment und durch wen zu ersetzen.
ved
1
@ved Nein, es werden alle derzeit im Container vorhandenen Fragmente durch die aktuellen ersetzt.
Rubenjohn
330

Ein weiterer wichtiger Unterschied zwischen addund replaceist:

replaceEntfernt das vorhandene Fragment und fügt ein neues Fragment hinzu. Dies bedeutet, dass beim Drücken der Zurück-Taste das Fragment, das ersetzt wurde, beim onCreateViewAufrufen erstellt wird. Während adddie vorhandenen Fragmente beibehalten und ein neues Fragment hinzugefügt werden, bedeutet dies, dass das vorhandene Fragment aktiv ist und sich nicht im angehaltenen Zustand befindet. Wenn also eine Zurück-Taste gedrückt onCreateViewwird, wird das vorhandene Fragment (das Fragment, das vor dem neuen Fragment vorhanden war) nicht aufgerufen hinzugefügt).

In Bezug auf den Lebenszyklusereignisse des Fragments onPause, onResume, onCreateViewund andere Lebenszyklusereignisse werden im Fall in Anspruch genommen werden , der replaceaber sie würde nicht bei aufgerufen werden add.

Bearbeiten : Man sollte vorsichtig sein, wenn sie eine Art Ereignisbusbibliothek wie Greenrobots Eventbus verwendet und dasselbe Fragment wiederverwendet, um das Fragment über andere über zu stapeln add. In diesem Szenario ist der Ereignisbus in jeder Instanz des hinzugefügten Fragments aktiv , obwohl Sie die bewährte Methode befolgen und den Ereignisbus registrieren und die Registrierung onResumeaufheben onPause, da das addFragment keine dieser Fragmentlebenszyklusmethoden aufruft. Infolgedessen würde der Ereignisbus-Listener in jeder aktiven Instanz des Fragments dasselbe Ereignis verarbeiten, das möglicherweise nicht Ihren Wünschen entspricht.

Jeevan
quelle
1
Ich denke, ein Ansatz könnte darin bestehen, das Ereignis im obersten Fragment zu verarbeiten und cancelEventDelivery () aufzurufen, nachdem die Verarbeitung abgeschlossen ist. Weitere Informationen zu den Methoden cancelEventDelivery () finden Sie hier github.com/greenrobot/EventBus/blob/master/…
Jeevan
6
+1 von mir. Es ist sehr wichtig zu wissen, dass das Ersetzen des aktuellen Fragments durch ein neues Fragment bedeutet, dass das vorherige Fragment neu erstellt wird, um es beim Zurückspringen vom Fragmentstapel wiederherzustellen.
Andalus
onPause, onResume ist eng mit der Hostaktivität verbunden. Und sie haben beim Ersetzen des Fragments nicht angerufen.
Zar E Ahmer
Wenn Sie EventBus verwenden, können Sie das Fragment mit Tag hinzufügen und vom Fragment dieses Tags an das Ereignis übergeben. Überprüfen Sie trotzdem, ob alle Ereignisbusse aufgerufen werden. Geben Sie einfach an, welcher ausgeführt werden soll
user2582318
Sie müssen erwähnen, dass Sie addToBackStack () zusammen mit den Methoden add () oder replace () aufrufen.
Rahil008
99

Beispiel Eine Aktivität hat 2 Fragmente und wir verwenden FragmentManager, um mit addToBackstackjedem Fragment ein Layout in Aktivität zu ersetzen / hinzuzufügen

Verwenden Sie ersetzen

Gehe zu Fragment1

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

Gehe zu Fragment2

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

Pop Fragment2

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

Pop Fragment1

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

Verwenden Sie add

Gehe zu Fragment1

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

Gehe zu Fragment2

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

Pop Fragment2

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

Pop Fragment1

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

Beispielprojekt

Phan Van Linh
quelle
1
sollte nicht onPause()vorher onStop()bei jeder Pop- Aktion aufgerufen werden ?
iCantC
Hervorragende Antwort zur Unterscheidung zwischen 'add ()' und 'replace ()', obwohl bei addToBackStack () etwas fehlt. Upvote
Shirish Herwade
@ ShirishHerwade Ich glaube, er hat in beiden Fällen den Unterschied zwischen Hinzufügen und Ersetzen durch AddToBackStack gezeigt.
CyberShark
38

Obwohl es sich um eine alte Frage handelt, die bereits beantwortet wurde, können diese nächsten Beispiele möglicherweise die akzeptierte Antwort ergänzen und für einige neue Programmierer in Android wie ich nützlich sein.

Option 1 - "addToBackStack ()" wird niemals verwendet

Fall 1A - Hinzufügen, Entfernen und Klicken auf die Schaltfläche Zurück

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

Fall 1B - Hinzufügen, Ersetzen und Klicken auf die Schaltfläche Zurück

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 ()" wird immer verwendet

Fall 2A - Hinzufügen, Entfernen und Klicken auf die Schaltfläche Zurück

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

Fall 2B - Hinzufügen, Ersetzen, Entfernen und Klicken auf die Schaltfläche Zurück

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 ()" wird nicht immer verwendet (in den folgenden Beispielen gibt w / o an, dass es nicht verwendet wird)

Fall 3A - Hinzufügen, Entfernen und Klicken auf die Schaltfläche Zurück

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

Fall 3B - Hinzufügen, Ersetzen, Entfernen und Klicken auf die Schaltfläche Zurück

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
quelle
1
Gründlich genug. Guter Versuch!
pulp_fiction
Können wir also sagen, dass die Zurück-Schaltfläche beim Arbeiten mit Fragmenten ähnlich funktioniert wie die Funktion FragmentManager.popBackStack ()?
Tim und Struppi
tolle Antwort, kann nicht besser sein. Dies sollte als Antwort akzeptiert werden.
Shirish Herwade
25

Grundlegender Unterschied zwischen add()und replace()kann beschrieben werden als:

  • add() wird verwendet, um einfach ein Fragment zu einem Stammelement hinzuzufügen.
  • replace() verhält sich ähnlich, entfernt jedoch zuerst vorherige Fragmente und fügt dann das nächste Fragment hinzu.

Wir können den genauen Unterschied sehen, wenn wir addToBackStack()zusammen mit add()oder verwenden replace().

Wenn wir die Zurück-Taste nach drücken , wenn add()... onCreateView wird nie aufgerufen, aber replace()wenn wir die Zurück-Taste drücken, wird oncreateView jedes Mal aufgerufen.

Avanindra_dubey
quelle
1
Führt add () zu einer höheren Belastung des Android-Speichers, da die Ansicht des vorherigen Fragments nicht zerstört wird?
Derekyy
@Derekyy Ja, ich denke schon.
Arpit J.
ist das, wonach ich gesucht habe
parvez rafi
2

Wenn wir das erste Fragment hinzufügen -> Zweites Fragment mit der Methode 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();

            }
        });

Wenn wir add () im Fragment verwenden

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

Wenn wir replace () im Fragment verwenden

Gehen Sie mit der Methode replace () zum ersten Fragment zum zweiten Fragment in First -> Second

 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

Im Fall von First Fragment ersetzen wird diese Methode extra aufgerufen (onPause, onStop, onDestroyView wird extra aufgerufen)

E / Keshav FirstFragment: onPause

E / Keshav FirstFragment: onStop

E / Keshav FirstFragment: onDestroyView

Keshav Gera
quelle
0

Die Funktion Add and Replace des FragmentManger kann wie folgt beschrieben werden: 1. add bedeutet, dass das Fragment in den Fragment-Backstack eingefügt wird und bei einem bestimmten Frame angezeigt wird, den Sie bereitstellen

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

2.replace bedeutet, dass Sie das Fragment im angegebenen Frame durch ein anderes Fragment ersetzen

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

Das Hauptdienstprogramm zwischen den beiden besteht darin, dass beim Zurückstapeln durch Ersetzen das Fragment aktualisiert wird, durch Hinzufügen jedoch das vorherige Fragment nicht aktualisiert wird.

Raj Kavadia
quelle
0

Wichtig zu beachten:

Der Unterschied zwischen Ersetzen und Ersetzen durch Backstack besteht immer dann, wenn wir nur Ersetzen verwenden, dann wird das Fragment zerstört (ondestroy () wird aufgerufen) und wenn wir Ersetzen mit Backstack verwenden, werden Fragmente onDestroy () nicht aufgerufen (dh wenn die Zurück-Schaltfläche gedrückt wird, wird das Fragment aufgerufen mit seinem onCreateView ())

Lloyd Dcosta
quelle
0

Hier ist ein Bild, das den Unterschied zwischen add()und zeigtreplace()

Geben Sie hier die Bildbeschreibung ein

Die add()Methode fügt also weiterhin Fragmente über dem vorherigen Fragment in FragmentContainer hinzu.

Während replace()Methoden alle vorherigen Fragmente aus Containern löschen und dann in FragmentContainer hinzufügen.

Was ist addToBackStack?

addtoBackStackMethode kann mit add () und Ersetzungsmethoden verwendet werden. Es dient einem anderen Zweck in der Fragment-API.

Was ist der Zweck?

Die Fragment-API wird im Gegensatz zur Aktivitäts-API standardmäßig nicht mit der Zurück-Schaltfläche-Navigation geliefert. Wenn Sie zum vorherigen Fragment zurückkehren möchten, verwenden wir die Methode addToBackStack () in Fragment. Lassen Sie uns beide verstehen

Fall 1:

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

Geben Sie hier die Bildbeschreibung ein

Fall 2:

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

Geben Sie hier die Bildbeschreibung ein

Rohit Singh
quelle