Difference Between Add(), Replace(), and Addtobackstack()

Difference between add(), replace(), and addToBackStack()

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

Difference between add vs addToBackStack

Well if you call multiple times add method on FragmentTransaction like this

FragmentTransaction ft = fragmentManager.beginTransaction();

Fragment fragment1 = new Fragment();
ft.add(R.id.llContainer, fragment1, "fragment_one");

Fragment fragment2 = new Fragment();
ft.add(R.id.llContainer, fragment2, "fragment_two");

ft.commit();

then both the fragments that been added to FragmentTransaction will be shown as overlapping.

Sample Image

Now clicking back will close the application. It won't start the previous fragment.

Hope this is what you were looking for.

Basic difference between add() and replace() method of Fragment

The important difference is:

replace removes the existing fragment and adds a new fragment..

but 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).

For more information just visit this conversation.

What's the difference between using add().addToBackStack(), add().detach() and replace().addToBackStack() in a FragmentTransaction?

I researched more and apparently, the difference between detach() and addToBackStack () is in the life cycle of Fragment. When we add the Fragment in the back stack, is called in sequence the methods onPause(), onStop() and after the onDestroyView(). In this state, the fragment clean up the resources associated with its view and "stay" there waiting to be called again. Returning to the layout from the back stack is called the method onCreateView() just for the fragment to draw its user interface. Actually, the fragment isn't destroyed.

In the other side, when we use detach() to remove or replace the fragment, is called in sequence all same methods cited first (onPause(), onStop(), onDestroyView()) adding this two methods: onDestroy(), to do final cleanup of the fragment's state and onDetach(), to detach the fragment to being no longer associated with its activity.

Basically, behind the scenes, they don't have the same behavior: using the addToBackStack() the fragments remain instantiated and detach(), don't.

difference between fragmentTransaction.add and fragmentTransaction.replace

You can add multiple fragments to a container and they will be layered one on top of the other. If your fragments have transparent backgrounds you will see this effect and will be able to interact with the multiple fragments at the same time.

This is what will happen if you use FragmentTransaction.add on a container. Your added fragment will be placed on top of your existing fragment.

If you use FragmentTransaction.replace(R.id.container,fragment) it will remove any fragments that are already in the container and add your new one to the same container.

You can also use the add method without a container id and your fragment will simply be added to the list of fragments in the FragmentManager and you can recall these at any time by their Tag value.

You can still return to a previous configuration IF you added the transaction to back stack. You can do this even if a previous operation removed a fragment. The removed fragment is remembered in the transaction and popping the back stack brings it back.

FragmentTransaction::replace() with or without addToBackStack()

1.

.add(R.id.frgment_holder, frgmtA, frgmtA.NAME)
.commit();
.replace(R.id.frgment_holder, frgmtB, frgmtB.NAME)
.addToBackStack(frgmtB.NAME)
.commit();`

the replace will remove the frgmtA from the the holder and its onDestroyView will be called (but since it is referenced in the backstack’s transaction data, frgmtA is NOT destroyed). And the frgmtB will be added to the holder.
Since the frgmtA is not destroyed, the

getSupportFragmentManager().findFragmentByTag(frgmtA.NAME); 

will find it.

after then, press on back button, it will pop the top transaction from the backStack, then reversing the transaction. i.e. remove frgmtB from the holder and add frgmtA back to the holder. Since there is no more reference to frgmtB its onDestroy is called.

2.
in the case of

add frgmtA;
replace() with frgmtB; addToStack();
replace() with frgmtC; addToStack();

If want to back press to jump to frgmtA, need to override onBackPressed(), in it
do

popBackStack(frgmtB.NAME, POP_BACK_STACK_INCLUSIVE), 

which will toss out the transaction in the stack above stack entry named frgmtB.NAME and do reverse the transaction on it, which will add back the frgmtA in the holder.

Is it OK to addToBackStack and replace in a fragment transaction?

You can refer to the android designer guide for fragment transaction:
http://developer.android.com/guide/components/fragments.html

Specificly the snippet below:

// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();

So yes, what you are doing is the correct approach in replacing fragments.

Why Fragmenttransaction replace() acts like a add()?

I guess it is happening because the fragments are being replaced but they are also being added to the BackStack as follows:

BaseActivity.kt

// Note the .addToBackStack(null)
this.supportFragmentManager?.beginTransaction()?.replace(resId, newFragment)?.addToBackStack(null)?.commit()

From Documentation for addToBackStack

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.

You may want to check this question to check more info about the difference between add, replace and addToBackStack.

If you don't wanna to "remember and restore" the fragment transition, just remove the call to addToBackStack.

Edit

If you always want to return to first fragment, you can do:

Keep the addToBackStack(). So, the navigation history will be retained

this.supportFragmentManager?.beginTransaction()?.replace(resId, 

newFragment)?.addToBackStack(null)?.commit()

Override onBackPressed on MainActivity or BaseActivity and request to always return to first transaction commit:

override fun onBackPressed() {
if(this.supportFragmentManager?.getBackStackEntryCount() > 0) {
this.supportFragmentManager?.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
} else {
super.onBackPressed()
}
}

Just note this is a test code and I could not verify. Also, I'm not familiar with Kotlin. So, this was the best code I could come with... Test and let me know the result... For any case, you can get the ideia.

Another option:

Remove the addToBackStack():

this.supportFragmentManager?.beginTransaction()?.replace(resId, newFragment)?.addToBackStack(null)?.commit()

Then, you must manually control which fragment should be displayed when user presses the back key... something like:

private var int : mCurrentFragment = 1

private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_home -> {
mCurrentFragment = 1
...
}
R.id.navigation_dashboard -> {
mCurrentFragment = 2
...
}
R.id.navigation_notifications -> {
mCurrentFragment = 3
...
}
}
false
}

override fun onBackPressed() {
if(mCurrentFragment != 1) {
replaceFragment(R.id.container_main_layout, Fragment1())
} else {
super.onBackPressed()
}
}


Related Topics



Leave a reply



Submit