The Code A is from the end branch of the official sample project。
When I click the Tab of the UI, the App will show the corresponding UI, and the current Tab will be marked as a different style.
In Overview.name Tab UI page, if I click a account item, the code composable(Overview.name) {... onAccountClick = { name -> navigateToSingleAccount(navController, name) }
will navigate it to composable( route = "$accountsName/{name}", ..)
UI , and Accounts.name is marked as current Tab.
What make me confuse is why Android can make Accounts.name as current Tab, could you tell me? Will navController.navigate()
cause Android recomposition
? so is val currentScreen = RallyScreen.fromRoute(backstackEntry.value?.destination?.route)
re-executed ?
Code A
@Composable
fun RallyApp() {
RallyTheme {
val allScreens = RallyScreen.values().toList()
val navController = rememberNavController()
val backstackEntry = navController.currentBackStackEntryAsState()
val currentScreen = RallyScreen.fromRoute(backstackEntry.value?.destination?.route)
Scaffold(
topBar = {
RallyTabRow(
allScreens = allScreens,
onTabSelected = { screen ->
navController.navigate(screen.name)
},
currentScreen = currentScreen
)
}
) { innerPadding ->
RallyNavHost(navController, modifier = Modifier.padding(innerPadding))
}
}
}
@Composable
fun RallyNavHost(navController: NavHostController, modifier: Modifier = Modifier) {
NavHost(
navController = navController,
startDestination = Overview.name,
modifier = modifier
) {
composable(Overview.name) {
OverviewBody(
onClickSeeAllAccounts = { navController.navigate(Accounts.name) },
onClickSeeAllBills = { navController.navigate(Bills.name) },
onAccountClick = { name ->
navigateToSingleAccount(navController, name)
},
)
}
composable(Accounts.name) {
AccountsBody(accounts = UserData.accounts) { name ->
navigateToSingleAccount(navController = navController, accountName = name)
}
}
composable(Bills.name) {
...
}
val accountsName = Accounts.name
composable(
route = "$accountsName/{name}",
arguments = listOf(
navArgument("name") {
type = NavType.StringType
}
),
deepLinks = listOf(
navDeepLink {
uriPattern = "rally://$accountsName/{name}"
}
),
) { entry ->
val accountName = entry.arguments?.getString("name")
val account = UserData.getAccount(accountName)
SingleAccountBody(account = account)
}
}
}
private fun navigateToSingleAccount(navController: NavHostController, accountName: String) {
navController.navigate("${Accounts.name}/$accountName")
}
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.")
}
}
}
CodePudding user response:
Yes, navigate()
will definitely cause recomposition as the UI is getting re-created.
Yes, val currentScreen = RallyScreen.fromRoute(backstackEntry.value?.destination?.route)
will be re-executed as backstackEntry
is being observed as state and its value will change when you navigate. That's why the RallyApp
composable will also get recomposed. So when it is executed again, currentScreen
value will get updated.