Multiple Back Stacks

Ken Baldauf

Senior Software Engineer @ Acorns

FragmentManager Changes

  • androidx.fragment 1.3.0
    • Substantial rewrite of fragment internals
    • Creates a new state manager: FragmentStateManager
      • Moves fragments through their lifecycle methods
      • Runs animations & transitions
      • Handles postponed transactions
      • Allows greater control over onSaveInstanceState().
    • Creates a new SpecialEffectsController
      • Source of truth for what should be happening with a fragment container
      • Handles animations/transitions associated with entering & exiting fragments.

A Peak Behind The Curtain

  • SpecialEffectController - manages state @ container level
  • FragmentStateManager - manages state @ fragment level
  • FragmentManager - manages state that applies to all fragments

FragmentManager Changes

  • androidx.fragment 1.4.0
    • Adds support for handling multiple back stacks
      • Built upon fragment changes made in 1.3.0
      • Adds two new APIs to facilitate support
        • saveBackStack
        • restoreBackStack
      • Existing APIs remain unchanged
    • Additional dependencies
      • AppCompat 1.4.0 is needed to avoid IDE issues
      • Navigation 2.4.0 needed if using Nav Component

Multiple Back Stack Support

  • Built off existing fragment transaction infrastructure.
  • Works by replaying previously ran fragment transactions.
  • All fragment transactions must call
    • saveToBackStack(name: String?)
      • Not doing so will lead to lost screens during restore
      • name used here later acts as key for the new APIs
    • setReorderingAllowed(true)
      • ​Ensures transaction can be restore in a single, atomic operation.
      • restoreBackStack(..) crashes if missing

New FragmentManager APIs

  • FragmentManager.saveBackStack(name: String)
    • saves the current back stack to internal memory
    • performs an inclusive pop to remove all of the fragments that were saved.
    • Unlike popBackStack(), ensures we don't destroy:
      • view state
      • saved instance state
      • ViewModel instances
  • FragmentManager.restoreBackStack(name: String)
    • pushes the full saved back stack onto the app’s current back stack.
  • Both no-op if name doesn't match an addToBackStack call

Visualize the Back Stack

// This is the initial 
// fragment the user sees
fragmentManager.commit {
  setReorderingAllowed(true)
  replace<HomeFragment>(R.id.container)
}
// add transactions to the back stack
fragmentManager.commit {
  setReorderingAllowed(true)
  replace<ProfileFragment>(R.id.container)
  addToBackStack(“profile”)
}
fragmentManager.commit {
  setReorderingAllowed(true)
  replace<EditProfileFragment>(R.id.container)
  addToBackStack(“edit_profile”)
}

Visualize the Back Stack

// save current back stack
fragmentManager.saveBackStack("profile")

// add new fragament transaction
fragmentManager.commit {
  setReorderingAllowed(true)
  replace<NotificationsFragment>(R.id.container)
  addToBackStack("notifications")
}

Visualize the Back Stack

// save current back stack
fragmentManager.saveBackStack(“notifications”)

// restore prior back stack
fragmentManager.restoreBackStack(“profile”)

Additional Reading

Questions?

Multiple Back Stack Support

By Kenneth Baldauf

Multiple Back Stack Support

Taking a look at FragmenManager's new APIs that serve as the driving force behind multiple back stack support.

  • 306