Skip to content

4. How to use with Fragments

Gabor Varadi edited this page Nov 15, 2021 · 5 revisions

Rationale

Fragment backstack only contains operations, but does not expose what Fragments currently exist.

Also, the BackstackChangeListener only provides the fact that the backstack has changed, but it does not tell you either the previous state, nor the new state.

Using Simple-Stack, it is possible to keep track of what Fragments are currently active, and simplify navigation between them.

Typical usage

First, add the simple-stack-extensions as a dependency.

implementation("com.github.Zhuinden:simple-stack-extensions:2.+")

Then we can use the defaults:

class ProfileFragment: KeyedFragment(R.layout.profile_fragment) {
    // ...
    @Override
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val key: ProfileKey = getKey()
    }

Where ProfileKey is:

@Parcelize
class ProfileKey: DefaultFragmentKey() {
    override fun instantiateFragment(): Fragment = ProfileFragment()
}

Providing navigation

We can use the DefaultFragmentStateChanger to handle most scenarios.

It will:

  • remove all fragments that no longer exist
  • add the current fragment if it doesn't exist
  • show the current fragment if it already exists but is hidden
  • any fragments that still exist but are not shown are hidden

Then the code in Activity should be as simple as:

class MainActivity : AppCompatActivity(), SimpleStateChanger.NavigationHandler {
    private lateinit var fragmentStateChanger: DefaultFragmentStateChanger

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)

        fragmentStateChanger = DefaultFragmentStateChanger(supportFragmentManager, R.id.root)

        Navigator.configure()
            .setStateChanger(SimpleStateChanger(this))
            .install(this, root, History.of(FirstKey()))
    }

    override fun onBackPressed() {
        if (!Navigator.onBackPressed(this)) {
            super.onBackPressed()
        }
    }

    override fun onNavigationEvent(stateChange: StateChange) {
        fragmentStateChanger.handleStateChange(stateChange)
    }
}