-
Notifications
You must be signed in to change notification settings - Fork 5
Compose Navigator Setup
This setup is an excerpt from Basic Sample app.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
val navigator = ComposeNavigator.with(this, savedInstanceState).initialize()
setContent {
...
MainScreen(navigator)
}
}
}
@Composable
fun MainScreen(navigator: ComposeNavigator) {
// starts here...
}
This will automatically manage back navigation whenever a backpress occurs. You can disable default back navigation logic for backpress using disableDefaultBackPressLogic()
when configuring Navigator from Builder options.
The savedInstanceState
will ensure that all the necessary backstack operations are saved (when appropriate lifecycle occurs) & will be restored after the configuration or process death.
Destinations can be represented as children of a sealed
class.
The constructor parameters becomes the arguments for the destination screen. Note, only data types that can be stored in a bundle are supported.
sealed class MainRoute : Route {
@Immutable @Parcelize
data class First(val data: String) : MainRoute()
@Immutable @Parcelize
data class Second(private val noArg: String = "") : MainRoute() // no arg route
companion object Key : Route.Key<MainRoute> // <-- Unique key for the root
}
@Composable // associated with MainRoute.First
fun FirstScreen(data: String, changed: (screen: Route) -> Unit) {...}
@Composable // associated with MainRoute.Second
fun SecondScreen() {...}
The MainRoute
must implement com.kpstv.navigation.compose.Route
interface which internally implements Parcelable
to ensure that the state of navigation will persist accross configuration change.
We also have declared a key
variable in the companion object
of the MainRoute
(which will be used during Setup). This key will be used to uniquely identify the Route
in the composition tree. This is how findNavController<T>()
was able to find & retrieve the Controller associated with that specified key.
From above snippet, you can notice we have declared a private noArg
parameter for Second
screen. The reason is we should not use object
or simple class
to represent empty argument constructor because SaveStateProvider
does not restore rememberSaveable
s after process death. Read more about this issue here.
@Composable
fun MainScreen(navigator: ComposeNavigator) {
// create instance of navigation controller to manage
// navigation of type MainRoute.
val navController = rememberNavController<MainRoute>()
navigator.Setup(key = MainRoute.key, initial = MainRoute.First("Hello world"), controller = navController) { dest ->
val onChanged: (screen: MainRoute) -> Unit = { value ->
navController.navigateTo(value)
}
when (dest) {
is MainRoute.First -> FirstScreen(dest.data, onChanged)
is MainRoute.Second -> SecondScreen()
}
}
}
Navigation to other destination is managed within the respective @Composable
screens. To go back programmatically you can call controller.goBack()
.
Each Setup
provides a unique instance of Controller<T>
for managing destination & can be accessed by using findNavController(key)
within child composables.
A when statement is used to switch between different @Composable
screens based on the target destination dest
.