When implementing BottomNavigation in Android, one common decision is whether to switch fragments using replace or add + show/hide.
This post documents my experience and reasoning when moving from the replace approach to add/show/hide for better performance and state preservation.
The Original replace Approach
supportFragmentManager.commit {
setReorderingAllowed(true)
replace(binding.fcvFragment.id, fragmentClass, null)
}
How It Works
- Completely removes the current fragment and creates a new fragment instance.
- The removed fragment goes through onDestroyView() and onDestroy() and is released from memory.
Pros
- Prevents unnecessary memory usage.
- Always builds the UI from scratch, making initialization logic straightforward.
Cons
- Fragment state (scroll position, input values, filters, etc.) is lost every time.
- Fragment creation cost occurs repeatedly, slowing down frequent tab switches.
The Improved add + show/hide Approach
supportFragmentManager.commit {
setReorderingAllowed(true)
supportFragmentManager.fragments.forEach { if (it.isVisible) hide(it) }
if (targetFragment == null) {
add(binding.fcvFragment.id, fragmentClass, null, tag)
} else {
show(targetFragment)
}
}
How It Works
- Creates the fragment (add()) only on the first visit.
- If the fragment already exists, it simply calls show() to make it visible.
- Other fragments are hide()-ed but kept in memory.
Pros
- State preservation: Scroll position, input values, and filters remain.
- Faster tab switching: No fragment creation cost on subsequent visits.
Cons
- Hidden fragments still occupy memory.
- onCreateView() is not called again, so if you need UI reinitialization, you must handle it manually.
replace vs add/show/hide
| Criteria | replace | add/show/hide |
| State preservation | ❌ Always resets | ✅ Preserves state |
| Memory usage | Lower | Higher |
| Switch speed | Slower | Faster |
| Init logic | Simple | Needs extra handling |
- Use add/show/hide when the user frequently switches tabs or when state preservation is important.
- Use replace when memory conservation is critical or when each visit should start with a fresh UI.
API Call Timing with show/hide
When using replace, it’s fine to call APIs during fragment creation (onViewCreated, for example).
However, with show/hide, lifecycle callbacks may not be triggered when a fragment becomes visible.
In fact, calling show() does not trigger onResume(), which can cause you to miss the right moment for refreshing data.
Solution: Using onHiddenChanged
I discovered that the onHiddenChanged callback can be used to detect when a fragment becomes visible again.
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (!hidden) {
viewModel.fetchAll()
}
}
When hidden is false, it means the fragment is now visible, so this is a good time to refresh data.
By switching to add + show/hide, I was able to significantly improve tab switching speed and maintain the user’s state between navigations.
That said, this approach comes with higher memory usage, so it’s important to choose the right strategy based on your app’s requirements.
'Android' 카테고리의 다른 글
| Retrofit에서 Ktor로: 안드로이드 HTTP 클라이언트 마이그레이션 (0) | 2026.01.08 |
|---|---|
| [Android] Safely Refreshing Tokens with Authenticator and Mutex (0) | 2025.09.10 |
| [Android] When Exactly Is onPause() Called? (3) | 2025.07.22 |