¿Cómo eliminar inputs duplicadas de FragmentManager?

Tengo una actividad simple con BottomNavigationView . Estoy usando fragments para implementar los contenidos de la actividad para las diferentes páginas.

Cuando el usuario presiona el button Atrás, se supone que debe regresar a la página vista anteriormente. El problema es que cuando se alterna repetidas veces entre las páginas (fragments), se registra todo este historial. Toma este ejemplo:

A -> B -> A -> B -> C -> A -> C

Presionar el button Atrás resultaría en el reverso, pero en cambio quiero este comportamiento (lo noté en la aplicación de Instagram):

C -> A -> B -> Salir de la aplicación

Entonces, cada fragment solo debe tener una input en el backstack. ¿Cómo hago esto? ¿Debo eliminar las transactions anteriores para un fragment de la stack?

¿Es esto posible con un FragmentManager? ¿O tengo que implementar el mío?

Mi actividad con BottomNavigationView:

 class ActivityOverview : AppCompatActivity() { // Listener for BottomNavigationView private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item -> when (item.itemId) { R.id.navigation_home -> { // "Home" menu item pressed setActiveFragment(resources.getString(R.string.tag_fragment_home)) return@OnNavigationItemSelectedListener true } R.id.navigation_dashboard -> { // "Dashboard" menu item pressed return@OnNavigationItemSelectedListener true } R.id.navigation_settings -> { // "Settings" menu item pressed setActiveFragment(resources.getString(R.string.tag_fragment_settings)) return@OnNavigationItemSelectedListener true } } false } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_overview) navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener) navigation.menu.findItem(R.id.navigation_home).setChecked(true) // Set initial fragment setActiveFragment(resources.getString(R.string.tag_fragment_home)) } override fun onBackPressed() { // > 1 so initial fragment addition isn't removed from stack if (fragmentManager.backStackEntryCount > 1) { fragmentManager.popBackStack() } else { finish() } } // Update displayed fragment fun setActiveFragment(tag: String) { val fragment = if (fragmentManager.findFragmentByTag(tag) != null) { // Fragment is already initialized if (fragmentManager.findFragmentByTag(tag).isVisible) { // Fragment is visible already, don't add another transaction null } else { // Fragment is not visible, add transaction fragmentManager.findFragmentByTag(tag) } } else { // Fragment is not initialized yet when (tag) { resources.getString(R.string.tag_fragment_home) -> FragmentHome() resources.getString(R.string.tag_fragment_settings) -> FragmentSettings() else -> null } } if (fragment != null) { val transaction = fragmentManager.beginTransaction() transaction.replace(R.id.container_fragment, fragment, tag) transaction.addToBackStack(null) transaction.commit() } } } 

En este punto, estoy bastante seguro de que no funciona con FragmentManager, así que creé una class para implementar una stack que no permite duplicates:

 class NoDuplicateStack<T> { val stack: MutableList<T> = mutableListOf() val size: Int get() = stack.size // Push element onto the stack fun push(p: T) { val index = stack.indexOf(p) if (index != -1) { stack.removeAt(index) } stack.add(p) } // Pop upper element of stack fun pop(): T? { if (size > 0) { return stack.removeAt(stack.size - 1) } else { return null } } // Look at upper element of stack, don't pop it fun peek(): T? { if (size > 0) { return stack[stack.size - 1] } else { return null } } } 

Luego integé esta class en mi actividad:

 class ActivityOverview : AppCompatActivity() { val fragmentsStack = NoDuplicateStack<String>() val fragmentHome = FragmentHome() val fragmentSettings = FragmentSettings() val fragmentHistory = FragmentHistory() // Listener for BottomNavigationView private val mOnNavigationItemSelectedListener = ... override fun onCreate(savedInstanceState: Bundle?) { ... } override fun onBackPressed() { if (fragmentsStack.size > 1) { // Remove current fragment from stack fragmentsStack.pop() // Get previous fragment from stack and set it again val newTag = fragmentsStack.pop() if (newTag != null) { setActiveFragment(newTag) } } else { finish() } } // Update displayed fragment fun setActiveFragment(tag: String) { val fragment = when (tag) { resources.getString(R.string.tag_fragment_home) -> fragmentHome resources.getString(R.string.tag_fragment_settings) -> fragmentSettings resources.getString(R.string.tag_fragment_history) -> fragmentHistory else -> null } if (fragment != null && !fragment.isVisible) { fragmentManager.beginTransaction() .replace(R.id.container_fragment, fragment, tag) .commit() fragmentsStack.push(tag) } } } 
  • reference no resuelta: text - Android Studio + Kotlin (findViewById fault?)
  • el timer se bloquea con KotlinNullPointerException dentro del fragment
  • Extender apropiadamente una class de Widget usando Kotlin
  • ¿Puedo tener un tipo de devolución diferente en kotlin?
  • Android NestedScrollView.smoothScrollBy () desplazándose demasiado
  • Kotlin stdlib operatios vs for loops
  • Herencia de Kotlin
  • La asignación de Firebase a Kotlin-Object no funciona
  • ¿Cómo especificar la versión de RxJava al usar RxKotlin?
  • ¿Cómo consultar el tipo de datos de reference Firebase Firestre?
  • Android Espresso: ¿cómo se verifica la vista antes de que la actividad termine?