If you’ve been working with Android and Fragments, you’ve probably faced this decision: should I use add() or replace() when switching Fragments?
It might sound simple — but the difference between FragmentTransaction.add() and FragmentTransaction.replace() can lead to bugs, memory leaks, or even unexpected UI behavior if misunderstood.
This guide breaks it down clearly and aligns with modern best practices, especially if you’re using Kotlin and Jetpack components.
What Are add() and replace() in Fragment Transactions?
When working with FragmentManager, you use FragmentTransaction to display Fragments in your app. Two core methods you’ll come across:
add(containerViewId, fragment)replace(containerViewId, fragment)
Both methods attach a Fragment to your UI, but they do so differently under the hood.
Let’s see how.
add() — Append, Don’t Replace
supportFragmentManager.beginTransaction()
.add(R.id.fragment_container, FirstFragment())
.addToBackStack(null)
.commit()What it does:
- Places the new Fragment on top of the existing one.
- The old Fragment is still in memory, and still part of the FragmentManager.
- It doesn’t destroy or detach the previous Fragment.
It’s like stacking one card on top of another — the card below is still there, just not visible.
Pros:
- Keeps the previous Fragment state
- Useful when you want to come back to the previous Fragment without recreation
- Ideal for flows where back navigation is important (e.g., form wizards, onboarding)
Cons:
- Can lead to multiple Fragments overlapping, if you’re not careful
- May consume more memory if you stack too many
replace() — Out With the Old, In With the New
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, SecondFragment())
.addToBackStack(null)
.commit()What it does:
- Removes the existing Fragment from the container.
- Destroys its view hierarchy.
- Adds the new Fragment in its place.
Think of swapping one picture frame for another — the old one is removed completely.
Pros:
- Keeps the Fragment stack cleaner
- Avoids UI overlap
- Saves memory in complex flows
Cons:
- Destroys previous Fragment’s state (unless manually handled)
- Recreates the old Fragment if you navigate back
So When Should You Use add() or replace()?
Use add() when:
- You need to preserve the previous Fragment’s state.
- You’re building a flow where users can go back to the same exact screen without reloading it.
- You have multiple Fragment layers (like dialogs, bottom sheets, or nested flows).
Use replace() when:
- You want a clean switch without preserving the old Fragment.
- You don’t need to reuse the previous Fragment state.
- You’re swapping between main tabs or screens (e.g., Home → Profile → Settings).
A Quick Reference: add() vs replace()
| Feature | add() | replace() |
|---|---|---|
| Keeps previous Fragment | Yes | No |
| Overlaps Fragments | Possible | No |
| Back stack behavior | Preserves all | Can restore, but recreates |
| Memory usage | Higher | Lower |
| Ideal for | Wizard flows, multi-layer UI | Tab switching, top-level views |
Pro Tips for Using Fragment add() and replace()
1. Always use addToBackStack() if you want to support back navigation. Without it, pressing back will exit the activity.
2. With add(), make sure to hide() or detach() previous Fragments if you don’t want visual overlap.
val transaction = supportFragmentManager.beginTransaction()
transaction.hide(currentFragment)
transaction.add(R.id.fragment_container, newFragment)
transaction.addToBackStack(null)
transaction.commit()3. If you’re using Jetpack Navigation Component, add() and replace() are abstracted — but under the hood, it still uses replace() behavior.
4. Avoid memory leaks: If using add(), remember that Fragments left in memory can still hold references to Views, Context, etc. Clean them up..!
5. Keep fragment tags consistent when using add() so you can retrieve them via findFragmentByTag() later.
Jetpack Compose Developers — Does This Still Matter?
If you’ve switched to Jetpack Compose, and you’re using NavHost with Navigation Compose, you’re no longer directly dealing with add() or replace().
Compose’s navigation system manages screen state using a backstack model, more akin to replace(). But understanding this topic still matters if:
- You’re migrating from legacy Views to Compose.
- You’re using Fragments to host Compose screens in a hybrid setup.
Final Verdict: Fragment add() vs replace() — Choose Wisely
Choosing between Fragment add() or replace() is more than just a technical decision — it’s about managing user experience, performance, and memory.
- If you’re building dynamic UIs with nested Flows — lean on
add()with careful state management. - If you’re keeping your app lean and focused —
replace()is your friend.
The key is knowing what each does under the hood, so your Fragment transactions are intentional, predictable, and maintainable.
Over to You
Next time you write a FragmentTransaction, ask yourself:
Do I need the old Fragment to stick around, or not?
That one question will guide you every time.
TL;DR
add()→ Keeps old Fragment, good for preserving state.replace()→ Destroys old Fragment, cleaner transitions.- Be careful with overlapping Fragments when using
add() - Use
addToBackStack()if you want back navigation. - Prefer
replace()for main screens,add()for layered UIs.
