Difference between add(), replace(), and addToBackStack()
Asked Answered
K

9

366

What is the main difference between calling these methods:

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

What does it mean to replace an already existing fragment, and adding a fragment to the activity state, and adding an activity to the back stack?

Secondly, with findFragmentByTag(), does this search for tag added by the add()/replace() method or the addToBackStack() method?

Kristin answered 5/9, 2013 at 10:43 Comment(0)
C
377

1) fragmentTransaction.addToBackStack(str);

Description - Add this transaction to the back stack. This means that the transaction will be remembered after it is committed, and will reverse its operation when later popped off the stack.

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

Description - Replace an existing fragment that was added to a container. This is essentially the same as calling remove(Fragment) for all currently added fragments that were added with the same containerViewId and then add(int, Fragment, String) with the same arguments given here.

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

Description - Add a fragment to the activity state. This fragment may optionally also have its view (if Fragment.onCreateView returns non-null) into a container view of the activity.

What does it mean to replace an already existing fragment, and adding a fragment to the activity state and adding an activity to the back stack ?

There is a stack in which all the activities in the running state are kept. Fragments belong to the activity. So you can add them to embed them in a activity.

You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. This is essentially useful when you have defined your fragment container at different layouts. You just need to replace with any other fragment in any layout.

When you navigate to the current layout, you have the id of that container to replace it with the fragment you want.

You can also go back to the previous fragment in the backStack with the popBackStack() method. For that you need to add that fragment in the stack using addToBackStack() and then commit() to reflect. This is in reverse order with the current on top.

findFragmentByTag does this search for tag added by the add/replace method or the addToBackStack method ?

If depends upon how you added the tag. It then just finds a fragment by its tag that you defined before either when inflated from XML or as supplied when added in a transaction.

References: FragmentTransaction

Careless answered 5/9, 2013 at 10:51 Comment(4)
So, can i add fragment by replace method at the beginning activity initiated?Nondescript
(No fragment was added before)Nondescript
Can a fragment container contains more than one fragment, If yes than how replace() method will behave. WIll it replace all the frgaments in that container or android api have a method that accept three arguments, i.e. frgamentContainer, new fragment and with whom to replace.Earache
@Earache No, it will replace all fragments currently existing in the container with the current one.Quell
R
401

One more important difference between add and replace is this:

replace removes the existing fragment and adds a new fragment. This means when you press back button the fragment that got replaced will be created with its onCreateView being invoked. Whereas add retains the existing fragments and adds a new fragment that means existing fragment will be active and they wont be in 'paused' state hence when a back button is pressed onCreateView is not called for the existing fragment(the fragment which was there before new fragment was added).

In terms of fragment's life cycle events onPause, onResume, onCreateView and other life cycle events will be invoked in case of replace but they wont be invoked in case of add.

Edit: One should be careful if she is using some kind of event bus library like Greenrobot's Eventbus and reusing the same fragment to stack the fragment on top of other via add. In this scenario, even though you follow the best practice and register the event bus in onResume and unregister in onPause, event bus would still be active in each instance of the added fragment as add fragment wont call either of these fragment life cycle methods. As a result event bus listener in each active instance of the fragment would process the same event which may not be what you want.

Ramunni answered 10/2, 2014 at 17:56 Comment(7)
I think one approach could be to process the event in the top most fragment and call cancelEventDelivery() after processing is complete. You can find more about the cancelEventDelivery() methods here github.com/greenrobot/EventBus/blob/master/…Ramunni
+1 from me. Very important to know that replacing current fragment with new fragment, means that previous fragment will be recreated to get it back when popping back from fragment stack.Retinoscopy
onPause, onResume is tightly associated to Host Activity. And they didn't call when replacing fragment.Dinerman
Just to add to this, if you are using EventBus you can add the fragment with Tag, and pass from fragment that tag to the event, and check anyway, all eventbus will be called, you just specify which one should executeMotorize
You must mention that you are calling addToBackStack() along with add() or replace() methods.Clupeid
so basically, use replace instead of add for a fragment that fills its containerDeandreadeane
This is super relevant even today, as we use menuProviders. MenuProviders that need to follow its Fragment's lifecycle must have a fragment whose transaction was replace.Ruthieruthless
C
377

1) fragmentTransaction.addToBackStack(str);

Description - Add this transaction to the back stack. This means that the transaction will be remembered after it is committed, and will reverse its operation when later popped off the stack.

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

Description - Replace an existing fragment that was added to a container. This is essentially the same as calling remove(Fragment) for all currently added fragments that were added with the same containerViewId and then add(int, Fragment, String) with the same arguments given here.

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

Description - Add a fragment to the activity state. This fragment may optionally also have its view (if Fragment.onCreateView returns non-null) into a container view of the activity.

What does it mean to replace an already existing fragment, and adding a fragment to the activity state and adding an activity to the back stack ?

There is a stack in which all the activities in the running state are kept. Fragments belong to the activity. So you can add them to embed them in a activity.

You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. This is essentially useful when you have defined your fragment container at different layouts. You just need to replace with any other fragment in any layout.

When you navigate to the current layout, you have the id of that container to replace it with the fragment you want.

You can also go back to the previous fragment in the backStack with the popBackStack() method. For that you need to add that fragment in the stack using addToBackStack() and then commit() to reflect. This is in reverse order with the current on top.

findFragmentByTag does this search for tag added by the add/replace method or the addToBackStack method ?

If depends upon how you added the tag. It then just finds a fragment by its tag that you defined before either when inflated from XML or as supplied when added in a transaction.

References: FragmentTransaction

Careless answered 5/9, 2013 at 10:51 Comment(4)
So, can i add fragment by replace method at the beginning activity initiated?Nondescript
(No fragment was added before)Nondescript
Can a fragment container contains more than one fragment, If yes than how replace() method will behave. WIll it replace all the frgaments in that container or android api have a method that accept three arguments, i.e. frgamentContainer, new fragment and with whom to replace.Earache
@Earache No, it will replace all fragments currently existing in the container with the current one.Quell
H
185

Here is a picture that shows the difference between add() and replace()

enter image description here

So add() method keeps on adding fragments on top of the previous fragment in FragmentContainer.

While replace() methods clears all the previous Fragment from Containers and then add it in FragmentContainer.

What is addToBackStack

addtoBackStack method can be used with add() and replace methods. It serves a different purpose in Fragment API.

What is the purpose?

Fragment API unlike Activity API does not come with Back Button navigation by default. If you want to go back to the previous Fragment then the we use addToBackStack() method in Fragment. Let's understand both

Case 1:

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

enter image description here

Case 2:

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

enter image description here

Herne answered 13/6, 2020 at 1:25 Comment(2)
pictures speak more than words.Tattle
what happen If in case 1 and 2 we use "replace" in the place of "add" ??Pink
M
177

Example an activity have 2 fragments and we use FragmentManager to replace/add with addToBackstack each fragment to a layout in activity

Use replace

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

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

Use add

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

Pop Fragment2

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

Pop Fragment1

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

Sample project

Malversation answered 5/1, 2018 at 3:48 Comment(5)
wasn't onPause() supposed to be called before onStop() on every Pop action ?Canoe
excellent answer to differentiate between 'add()' and 'replace()', though missing about addToBackStack(). UpvoteRackrent
@ShirishHerwade I believe he demonstrated difference between add and replace with addToBackStack on both cases.Messeigneurs
This is a way better answer other than just the theoryRevise
easy to remember than theoryKaltman
C
62

Although it is an old question already answered, maybe those next examples can complement the accepted answer and they can be useful for some new programmers in Android as I am.

Option 1 - "addToBackStack()" is never used

Case 1A - adding, removing, and clicking Back button

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

Case 1B - adding, replacing, and clicking Back button

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()" is always used

Case 2A - adding, removing, and clicking Back button

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

Case 2B - adding, replacing, removing, and clicking Back button

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()" is not used always (in the below examples, w/o indicates that it is not used)

Case 3A - adding, removing, and clicking Back button

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

Case 3B - adding, replacing, removing, and clicking Back button

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
Cardsharp answered 27/3, 2019 at 19:14 Comment(1)
So can we say that while working with fragments back button works in a similar fashion to the FragmentManager.popBackStack() function?Politburo
K
38

Basic difference between add() and replace() can be described as:

  • add() is used for simply adding a fragment to some root element.
  • replace() behaves similarly but at first it removes previous fragments and then adds next fragment.

We can see the exact difference when we use addToBackStack() together with add() or replace().

When we press back button after in case of add()... onCreateView is never called, but in case of replace(), when we press back button ... oncreateView is called every time.

Kiser answered 2/3, 2017 at 11:48 Comment(3)
So is add() results in more burden in terms of android memory, since the previous fragment's view is not destroyed?Remontant
@Remontant Yes, I think so.Relational
@Remontant it depends on use case. If there is a high chances that user will navigate to previous screen then I think replace will have more burden on memoryDoctor
D
7

Important thing to be noticed:

Difference between Replace and Replace with backstack is whenever we use only replace then the fragment is destroyed ( ondestroy() is called ) and when we use replace with backstack then fragments onDestroy() is not called ( i.e when back button is pressed fragment is invoked with its onCreateView())

Duma answered 21/3, 2020 at 6:28 Comment(1)
that's why people using fragment.getViewLifeCycle() in such cases: developer.android.com/guide/fragments/lifecycle#statesWilkinson
N
2

When We Add First Fragment --> Second Fragment using add() method

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

            }
        });

When we use add() in 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

When we use replace() in fragment

going to first fragment to second fragment in First -->Second using replace() method

 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

In case of Replace First Fragment these method is extra called ( onPause,onStop,onDestroyView is extra called )

E/Keshav FirstFragment: onPause

E/Keshav FirstFragment: onStop

E/Keshav FirstFragment: onDestroyView

Nicki answered 24/6, 2019 at 10:1 Comment(0)
K
0

The FragmentManger's function add and replace can be described as these 1. add means it will add the fragment in the fragment back stack and it will show at given frame you are providing like

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

2.replace means that you are replacing the fragment with another fragment at the given frame

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

The Main utility between the two is that when you are back stacking the replace will refresh the fragment but add will not refresh previous fragment.

Kandykane answered 5/9, 2019 at 7:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.