Różnica między add (), replace () i addToBackStack ()

300

Jaka jest główna różnica między wywoływaniem tych metod:

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

Co to znaczy zastąpić już istniejący fragment i dodać fragment do stanu działania oraz dodać działanie do tylnego stosu?

Po drugie, findFragmentByTag()czy to wyszukiwanie znacznika dodanego przez metodę add()/ replace()czy addToBackStack()metodę?

AndroidDev
źródło

Odpowiedzi:

330

1) fragmentTransaction.addToBackStack(str);

Opis - dodaj tę transakcję do tylnego stosu. Oznacza to, że transakcja zostanie zapamiętana po jej zatwierdzeniu i odwróci jej działanie, gdy później wyskoczy ze stosu.

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

Opis - zastąp istniejący fragment, który został dodany do kontenera. Jest to w zasadzie to samo, co wywołanie metody remove (Fragment) dla wszystkich obecnie dodanych fragmentów, które zostały dodane za pomocą tego samego kontenerViewViewId, a następnie dodania (int, Fragment, String) z tymi samymi argumentami podanymi tutaj.

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

Opis - Dodaj fragment do stanu aktywności. Ten fragment może opcjonalnie mieć również swój widok (jeśli Fragment.onCreateView zwraca wartość inną niż null) w widoku kontenera działania.

Co to znaczy zastąpić już istniejący fragment i dodać fragment do stanu działania i dodać działanie do tylnego stosu?

Istnieje stos, w którym przechowywane są wszystkie działania w stanie uruchomionym. Fragmenty należą do działania. Możesz więc dodać je, aby osadzić je w działaniu.

Możesz łączyć wiele fragmentów w jednym działaniu, aby zbudować wielopanelowy interfejs użytkownika i ponownie użyć fragmentu w wielu działaniach. Jest to zasadniczo przydatne, gdy zdefiniowano kontener fragmentów w różnych układach. Musisz tylko zastąpić dowolnym innym fragmentem w dowolnym układzie.

Po przejściu do bieżącego układu masz identyfikator tego kontenera, aby zastąpić go wybranym fragmentem.

Metodą możesz także wrócić do poprzedniego fragmentu backStack popBackStack(). W tym celu należy dodać ten fragment do stosu za pomocą, addToBackStack()a następnie commit()do odzwierciedlenia. Jest to w odwrotnej kolejności, z prądem na górze.

findFragmentByTag czy to wyszukiwanie tagu dodanego przez metodę add / replace lub addToBackStack?

Jeśli zależy od sposobu dodania tagu. Następnie po prostu znajduje fragment według swojego tagu, który zdefiniowałeś wcześniej albo po napompowaniu z XML, albo po dostarczeniu po dodaniu w transakcji.

Odniesienia: FragmentTransaction

Mój Boże
źródło
2
Czy mogę dodać fragment metodą zamiany na początku zainicjowanej aktywności?
Yohanes AI
(Nie dodano wcześniej żadnego fragmentu)
Yohanes AI
2
Czy kontener fragmentów może zawierać więcej niż jeden fragment, jeśli tak, to jak zachowa się metoda replace (). Pozwoli to zastąpić wszystkie frgamenty w tym kontenerze lub Android API ma metodę, która akceptuje trzy argumenty, tj. FrgamentContainer, nowy fragment i kim zastąpić.
przeciwko
1
@ved Nie, zastąpi wszystkie fragmenty aktualnie istniejące w kontenerze bieżącym.
reubenjohn
329

Jeszcze jedna ważna różnica między addi replaceto:

replaceusuwa istniejący fragment i dodaje nowy fragment. Oznacza to, że po naciśnięciu przycisku Wstecz zastąpiony fragment zostanie utworzony z jego onCreateViewwywołaniem. Podczas gdy addzachowuje istniejące fragmenty i dodaje nowy fragment, co oznacza, że ​​istniejący fragment będzie aktywny i nie będą one w stanie „wstrzymanym”, dlatego po naciśnięciu przycisku Wstecz onCreateViewnie jest wywoływany dla istniejącego fragmentu (fragment, który był tam przed nowym fragmentem, był dodany).

Jeśli chodzi o wydarzenia w cyklu życia fragment onPause, onResume, onCreateViewi innych imprez cyklu życia zostanie wywołany w przypadku replace, ale przyzwyczajenie się powoływać w przypadku add.

Edycja : Należy zachować ostrożność, jeśli używa ona jakiejś biblioteki magistrali zdarzeń, takiej jak Eventbus Greenrobota i ponownie wykorzystuje ten sam fragment do układania tego fragmentu na innym za pośrednictwem add. W tym scenariuszu, nawet jeśli postępujesz zgodnie z najlepszymi praktykami, rejestrujesz onResumei wyrejestrowujesz onPausemagistralę zdarzeń, magistrala zdarzeń nadal będzie aktywna w każdej instancji dodanego fragmentu, ponieważ addfragment nie wywoła żadnej z tych metod cyklu życia fragmentu. W rezultacie detektor szyny zdarzeń w każdej aktywnej instancji fragmentu przetworzyłby to samo zdarzenie, które może nie być tym, czego chcesz.

Jeevan
źródło
1
Myślę, że jednym z podejść może być przetworzenie zdarzenia w najwyższym fragmencie i wywołanie cancelEventDelivery () po zakończeniu przetwarzania. Więcej informacji na temat metod cancelEventDelivery () można znaleźć tutaj github.com/greenrobot/EventBus/blob/master/…
Jeevan
6
+1 ode mnie Bardzo ważne jest, aby wiedzieć, że zastąpienie bieżącego fragmentu nowym fragmentem oznacza, że ​​poprzedni fragment zostanie odtworzony, aby odzyskać go po wyskoczeniu ze stosu fragmentów.
AndaluZ
onPause, onResume jest ściśle powiązany z Aktywnością Hosta. I nie zadzwonili, zastępując fragment.
Zar E Ahmer,
Aby dodać do tego, jeśli używasz EventBus, możesz dodać fragment ze znacznikiem i przekazać z fragmentu tego znacznika do zdarzenia, i sprawdzić mimo wszystko, wszystkie eventbus zostaną wywołane, wystarczy określić, który należy wykonać
2582318
Musisz wspomnieć, że wywołujesz addToBackStack () wraz z metodami add () lub replace ().
rahil008
99

Przykład działania ma 2 fragmenty i używamy FragmentManagerdo zamiany / dodawania addToBackstackkażdego fragmentu do układu w działaniu

Użyj zamień

Idź Fragment 1

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

Przejdź fragment 2

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

Fragment Pop 2

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

Fragment popu 1

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

Użyj add

Idź Fragment 1

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

Przejdź fragment 2

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

Fragment Pop 2

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

Fragment popu 1

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

Przykładowy projekt

Phan Van Linh
źródło
1
nie onPause()miał być wcześniej nazywany onStop()przy każdej akcji Pop ?
iCantC
doskonała odpowiedź na rozróżnienie między „add ()” i „replace ()”, choć brakuje jej w addToBackStack (). Upvote
Shirish Herwade
@ShirishHerwade Wierzę, że wykazał różnicę między dodawaniem a zastępowaniem przez addToBackStack w obu przypadkach.
CyberShark
38

Chociaż jest to stare pytanie, na które już udzielono odpowiedzi, być może te kolejne przykłady mogą uzupełnić zaakceptowaną odpowiedź i mogą być przydatne dla niektórych nowych programistów w systemie Android, tak jak ja.

Opcja 1 - „addToBackStack ()” nigdy nie jest używane

Przypadek 1A - dodawanie, usuwanie i klikanie przycisku Wstecz

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

Przypadek 1B - dodawanie, zastępowanie i kliknięcie przycisku Wstecz

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

Opcja 2 - „addToBackStack ()” jest zawsze używana

Przypadek 2A - dodawanie, usuwanie i klikanie przycisku Wstecz

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

Przypadek 2B - dodawanie, zastępowanie, usuwanie i kliknięcie przycisku Wstecz

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

Opcja 3 - „addToBackStack ()” nie jest zawsze używane (w poniższych przykładach w / o oznacza, że ​​nie jest używane)

Przypadek 3A - dodawanie, usuwanie i klikanie przycisku Wstecz

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

Przypadek 3B - dodawanie, zastępowanie, usuwanie i kliknięcie przycisku Wstecz

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
źródło
1
Wystarczająco dokładny. Dobry wysiłek!
pulp_fiction
Czy możemy więc powiedzieć, że podczas pracy z fragmentami przycisk Wstecz działa w podobny sposób jak funkcja FragmentManager.popBackStack ()?
Tintin
świetna odpowiedź, nie mogę być lepszy. Należy zaakceptować odpowiedź.
Shirish Herwade
25

Podstawową różnicę między add()i replace()można opisać jako:

  • add() służy do zwykłego dodania fragmentu do jakiegoś elementu głównego.
  • replace() zachowuje się podobnie, ale najpierw usuwa poprzednie fragmenty, a następnie dodaje kolejny fragment.

Dokładną różnicę widzimy, gdy używamy addToBackStack()razem z add()lubreplace() .

Kiedy naciśniemy przycisk Wstecz po w przypadku add()... onCreateView nigdy nie jest wywoływany, ale w przypadku replace(), gdy naciśniemy przycisk Wstecz ... oncreateView jest wywoływany za każdym razem.

Avanindra_dubey
źródło
1
Czy add () powoduje większe obciążenie pamięci Android, ponieważ widok poprzedniego fragmentu nie jest zniszczony?
Derekyy,
@Derekyy Tak, tak myślę.
Arpit J.
właśnie tego szukałem
parvez rafi
2

Kiedy dodajemy pierwszy fragment -> Drugi fragment za pomocą metody 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();

            }
        });

Kiedy używamy add () we fragmencie

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

Kiedy używamy replace () we fragmencie

przejście do pierwszego fragmentu do drugiego fragmentu w Pierwszym -> Drugim za pomocą metody 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

W przypadku zamiany pierwszego fragmentu metoda ta jest wywoływana dodatkowo (onPause, onStop, onDestroyView jest wywoływany dodatkowo)

E / Keshav FirstFragment: onPause

E / Keshav FirstFragment: onStop

E / Keshav FirstFragment: onDestroyView

Keshav Gera
źródło
0

Funkcja FragmentManger dodaj i zamień można opisać następująco: 1. add oznacza, że ​​doda fragment do tylnego stosu fragmentu i pokaże w podanej ramce, którą podajesz

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

2.replace oznacza, że ​​zastępujesz fragment innym fragmentem w danej ramce

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

Główne narzędzie między nimi polega na tym, że po ponownym ułożeniu w stos zamiennik odświeży fragment, ale dodanie nie odświeży poprzedniego fragmentu.

raj kavadia
źródło
0

Ważna rzecz, na którą należy zwrócić uwagę:

Różnica między Zamień i Zamień z backstack polega na tym, że gdy używamy tylko zamiany, fragment jest niszczony (wywoływany jest ondestroy ()), a gdy używamy zamiany z backstack, wówczas fragmenty onDestroy () nie są wywoływane (tj. Po naciśnięciu przycisku Wstecz wywoływany jest fragment z jego onCreateView ())

Lloyd Dcosta
źródło
0

Oto zdjęcie, które pokazuje różnicę między add()ireplace()

wprowadź opis zdjęcia tutaj

Więc add()metoda stale dodając fragmenty na szczycie poprzednim fragmencie w FragmentContainer.

Podczas gdy replace()metody usuwają wszystko poprzednie fragmenty z kontenerów, a następnie dodają je do FragmentContainer.

Co to jest addToBackStack

addtoBackStackMetoda może być używana z metodami add () i replace. Służy do innego celu w Fragment API.

Co jest celem?

Fragment API w przeciwieństwie do API aktywności nie jest domyślnie wyposażony w nawigację z przyciskiem Wstecz . Jeśli chcesz wrócić do poprzedniego fragmentu, używamy metody addToBackStack () we fragmencie. Rozumiem oba

Przypadek 1:

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

wprowadź opis zdjęcia tutaj

Przypadek 2:

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

wprowadź opis zdjęcia tutaj

Rohit Singh
źródło