You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从ProfileScreen导航到LoginScreen?Jetpack Navigation报错解决

解决Jetpack Compose跨导航图导航失败问题

当从HomeNavGraph中的ProfileScreen尝试导航至AuthNavGraph的LoginScreen时,执行navController.navigate(AuthScreen.AuthenticationScreen.LoginScreen.route)抛出以下错误:

java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/login } cannot be found in the navigation graph NavGraph(0xd750ce95) route=main_graph startDestination={Destination(0x78d845ec) route=home}

原因:当前HomeNavGraph使用的是自身嵌套NavHost的控制器,该控制器仅能访问Home导航图内部的目的地,而AuthNavGraph属于RootNavGraph层级的导航图,不在子NavHost的管辖范围内,因此无法直接找到LoginScreen的路由。


方案1:调整导航结构,将HomeNavGraph作为RootNavGraph的嵌套导航

把Home的导航图直接整合到RootNavGraph的根NavHost中,让根控制器能直接访问所有导航目的地:

修改RootNavGraph

@Composable
fun RootNavGraph(tokenManager: TokenManager, navController: NavHostController) {
    NavHost(navController = navController, route = Graph.ROOT, startDestination = Graph.AUTH) {
        authNavGraph(tokenManager = tokenManager, navController = navController)
        // 将原来的composable替换为嵌套的navigation,整合Home导航图
        navigation(route = Graph.HOME, startDestination = BottomBarItem.Main.route) {
            homeNavGraph(navController)
        }
    }
}

object Graph{
    const val ROOT="root_graph"
    const val AUTH="auth_graph"
    const val HOME="main_graph"
}

将HomeNavGraph改为NavGraphBuilder扩展函数

fun NavGraphBuilder.homeNavGraph(navController: NavHostController) {
    val sharedViewModel: SharedViewModel = viewModel()
    
    composable(route = BottomBarItem.Main.route) {
        MainScreen(navController, sharedViewModel)
    }

    composable(route = BottomBarItem.Profile.route) {
        ProfileScreen(navController)
    }

    composable(route = BottomBarItem.Cart.route) {
        CartScreen(navController = navController)
    }

    composable(route = "details") {
        DetailScreen(sharedViewModel, navController)
    }

    composable(
        route = "catProducts/{id}",
        arguments = listOf(navArgument("id"){ type = NavType.StringType })
    ) {
        val id = it.arguments?.getString("id")!!
        CatProducts(id, navController, sharedViewModel)
    }

    composable(route = "checkout") {
        CheckoutScreen()
    }

    composable(route = "orders") {
        OrderScreen(navController)
    }

    composable(
        route = "orderDetail/{id}",
        arguments = listOf(navArgument("id"){ type = NavType.StringType })
    ) {
        val orderId = it.arguments?.getString("id")!!
        OrderDetailScreen(orderId)
    }
}

在ProfileScreen中使用根控制器导航

@Composable
fun ProfileScreen(navController: NavHostController) {
    // 示例退出登录按钮
    Button(onClick = {
        // 清除Home导航图的回退栈,避免返回键回到Home
        navController.popBackStack(Graph.HOME, inclusive = true)
        // 直接导航到LoginScreen
        navController.navigate(AuthScreen.AuthenticationScreen.LoginScreen.route)
    }) {
        Text("退出登录")
    }
}

方案2:保留嵌套NavHost,传递根控制器到ProfileScreen

如果需要保持HomeNavGraph作为独立的嵌套NavHost,可以通过传递根控制器来实现跨导航图导航:

修改HomeNavGraph传递根控制器

@Composable
fun HomeNavGraph(navController: NavHostController, paddingValues: PaddingValues) {
    val sharedViewModel: SharedViewModel = viewModel()
    // 获取根控制器,如果当前控制器没有父级则使用自身
    val rootNavController = navController.parent ?: navController
    
    NavHost(navController = navController, route = Graph.HOME, startDestination = BottomBarItem.Main.route ){
        // ...其他composable保持不变
        
        composable(route = BottomBarItem.Profile.route){
            // 传递根控制器给ProfileScreen
            ProfileScreen(rootNavController)
        }
    }
}

修改ProfileScreen使用根控制器导航

@Composable
fun ProfileScreen(rootNavController: NavHostController) {
    Button(onClick = {
        // 清除Home导航图的回退栈
        rootNavController.popBackStack(Graph.HOME, inclusive = true)
        // 导航到LoginScreen
        rootNavController.navigate(AuthScreen.AuthenticationScreen.LoginScreen.route)
    }) {
        Text("退出登录")
    }
}

关键说明:

  • 跨导航图导航必须使用根层级的NavHostController,子NavHost的控制器只能访问自身导航图内的目的地。
  • 使用popBackStack(Graph.HOME, inclusive = true)可以清除Home导航图的所有回退栈,确保用户从LoginScreen返回时不会回到Home界面。

内容的提问来源于stack exchange,提问作者Ashish Kamat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 09:15:23