Navigation with Child Stack¶
The StackNavigator¶
All navigation in Child Stack
is performed using the StackNavigator
interface, which is extended by the StackNavigation
interface.
StackNavigator
contains the navigate
method with the following arguments:
transformer
- converts the current stack of configurations into a new one. The stack is represented asList
, where the last element is the top of the stack, and the first element is the bottom of the stack.onComplete
- called when navigation is finished.
There is also navigate
extension function without the onComplete
callback, for convenience.
Warning
The configuration stack returned by the transformer
function must not be empty.
val navigation = StackNavigation<Configuration>()
The navigation process¶
During the navigation process, the Child Stack
compares the new stack of configurations with the previous one. The Child Stack
ensures that all removed components are destroyed, and that there is only one component resumed at a time - the top one. All components in the back stack are always either stopped or destroyed.
The Child Stack
usually performs the navigation synchronously, which means that by the time the navigate
method returns, the navigation is finished and all component lifecycles are moved into required states. However, the navigation is performed asynchronously in case of recursive invocations - e.g. pop
is called from onResume
lifecycle callback of a component being pushed. All recursive invocations are queued and performed one by one once the current navigation is finished.
StackNavigator extension functions¶
There are StackNavigator
extension functions to simplify the navigation. Some of which were already used in the Child Stack overview example.
The preceding examples will utilize the following sealed class
& navigation
for showcasing the usage of the StackNavigator
extensions.
sealed class Configuration {
object A : Configuration()
object B : Configuration()
object C : Configuration()
object D : Configuration()
}
val navigation = StackNavigation<Configuration>()
push¶
Pushes the provided Configuration
at the top of the stack.
[A, B*]
navigation.push(Configuration.C)
[A, B, C*]
pop¶
Pops the latest configuration at the top of the stack.
[A, B, C*]
navigation.pop()
// Or
navigation.pop { isSuccess ->
// Called when the navigation is finished.
// isSuccess - `true` if the stack size was greater than 1 and a component was popped, `false` otherwise.
}
[A, B*]
popWhile¶
Drops the configurations at the top of the stack while the provided predicate returns true.
[A, B, C, D*]
navigation.popWhile { topOfStack: Configuration -> topOfStack !is B }
[A, B*]
popTo(index)¶
Drops configurations at the top of the stack so that the provided index becomes active (the new top of the stack).
[A, B, C, D*]
navigation.popTo(index = 1)
[A, B*]
replaceCurrent¶
Replaces the current configuration at the top of the stack with the provided Configuration
.
[A, B, C*]
navigation.replaceCurrent(Configuration.D)
[A, B, D*]
bringToFront¶
Removes all components with configurations of the provided Configuration
's class, and adds the provided Configuration
to the top of the stack. This is primarily helpful when implementing a Decompose app with Bottom Navigation. See the related discussion in the old repository.
Note
The operation is performed as one transaction. If there is already a component with the same configuration, it will not be recreated.
[A, B, C*]
navigation.bringToFront(Configuration.B)
[A, C, B*]