The following code are from the official sample project.
There are two branches, main and end.
I found the Code main and the Code end using different ways to navigate.
Code main is simple and clear, and in other projects, it navigate based State just like Code A which is from the project.
Code end use NavHostController to navigate, but It seems that we need't to use Navigation again when we use Jetpack Compose, right?
Code main
@Composable
fun RallyApp() {
RallyTheme {
val allScreens = RallyScreen.values().toList()
var currentScreen by rememberSaveable { mutableStateOf(RallyScreen.Overview) }
Scaffold(
...
) { innerPadding ->
Box(Modifier.padding(innerPadding)) {
currentScreen.content(
onScreenChange = { screen ->
currentScreen = RallyScreen.valueOf(screen)
}
)
}
}
}
}
enum class RallyScreen(
val icon: ImageVector,
val body: @Composable ((String) -> Unit) -> Unit
) {
Overview(
icon = Icons.Filled.PieChart,
body = { OverviewBody() }
),
Accounts(
icon = Icons.Filled.AttachMoney,
body = { AccountsBody(UserData.accounts) }
),
Bills(
icon = Icons.Filled.MoneyOff,
body = { BillsBody(UserData.bills) }
);
@Composable
fun content(onScreenChange: (String) -> Unit) {
body(onScreenChange)
}
}
Code end
@Composable
fun RallyNavHost(navController: NavHostController, modifier: Modifier = Modifier) {
NavHost(
navController = navController,
startDestination = Overview.name,
modifier = modifier
) {
composable(Overview.name) {
OverviewBody(
...
)
}
composable(Accounts.name) {
...
}
composable(Bills.name) {
...
}
}
}
enum class RallyScreen(
val icon: ImageVector,
) {
Overview(
icon = Icons.Filled.PieChart,
),
Accounts(
icon = Icons.Filled.AttachMoney,
),
Bills(
icon = Icons.Filled.MoneyOff,
);
companion object {
fun fromRoute(route: String?): RallyScreen =
when (route?.substringBefore("/")) {
Accounts.name -> Accounts
Bills.name -> Bills
Overview.name -> Overview
null -> Overview
else -> throw IllegalArgumentException("Route $route is not recognized.")
}
}
Code A
fun CraneHomeContent(
...
) {
val suggestedDestinations by viewModel.suggestedDestinations.collectAsState()
val onPeopleChanged: (Int) -> Unit = { viewModel.updatePeople(it) }
var tabSelected by remember { mutableStateOf(CraneScreen.Fly) }
BackdropScaffold(
...
frontLayerContent = {
when (tabSelected) {
CraneScreen.Fly -> {
...
}
CraneScreen.Sleep -> {
...
}
CraneScreen.Eat -> {
...
}
}
}
)
}
To answer your question:
Code Mainis not the right way to navigate.This is an example to get started. In that case you simply hide and show Composables that's it.
Why is it better to use navigation?
Lifecylce is being handled better. Imagine you want to start a cameraX compasable screen and then you want to return back to your initial composable. Navigation component will handle and release the resources.
Composable are added to the back stack. So when you press back it automatically returns to previous screen composable.
You get this nice animation and you do not just see the next screen instantly.
I am sure there are other points as well but those are some that came up to my mind right now....