如何在嵌套导航图 Jet Compose 之间传递参数

发布于 2025-01-19 21:43:42 字数 7192 浏览 4 评论 0原文

我想将{id}从listScreen传递到详细信息。在列表屏幕上,当发生点击事件时,我开始导航到这样的详细信息。

navController.navigate(
                        route = AppDestination.UserProfile.passId(
                            friendId = it.friendId
                        )
                    )

详细说明,我通过这样的构造函数得到了那个朋友。

@Composable
fun UserProfileScreen(
    navController: NavController,
    friendId: Long,
) {
    UserProfileView(
        navController = navController,
        friendId = friendId
    )
}

在我的应用程序中,我只使用3个图表管理导航流。像Rootgraph,Authgraph和Homegraph一样。以下是导航代码。

object Routes {
    const val AUTH_ROUTE = "auth"
    const val HOME_ROUTE = "home"
    const val ROOT_ROUTE = "root"
}

object ArgsConstants{
    const val USER_PROFILE_KEY = "id"
}

sealed class AppDestination(val route: String) {
 //user
    object UserProfile : AppDestination(route = "user_profile_screen/{${ArgsConstants.USER_PROFILE_KEY}}"){
        fun passId(friendId : Long): String{

            return this.route.replace(
                oldValue = "{${ArgsConstants.USER_PROFILE_KEY}}",
                newValue = friendId.toString()
            )
        }
    }
}

这是我的根。

@Composable
fun RootNavGraph(
    navController: NavHostController
) {
    NavHost(
        navController = navController,
        startDestination = AppDestination.Branding.route,
        route = Routes.ROOT_ROUTE
    ) {
        composable(route = AppDestination.Branding.route) {
            BrandingScreen(navController = navController)
        }

        authNavGraph(navController = navController)
        homeNavGraph(navController = navController)

    }
}

这是我的身影。

fun NavGraphBuilder.authNavGraph(
    navController: NavHostController
) {
    navigation(
        startDestination = AppDestination.Language.route,
        route = Routes.AUTH_ROUTE
    ) {

        composable(route = AppDestination.Language.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            LanguageScreen(navController = navController, vm = authViewModel)
        }

        composable(route = AppDestination.Login.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            LoginScreen(navController = navController, vm = authViewModel)
        }

        composable(route = AppDestination.Signup.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            SignupScreen(navController = navController, vm = authViewModel)
        }

        composable(route = AppDestination.VerifiedAccount.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            VerifiedAccountScreen(navController = navController, vm = authViewModel)
        }
        composable(route = AppDestination.NoAccount.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            NoAccountScreen(navController = navController, vm = authViewModel)
        }
        composable(route = AppDestination.VerifiedMethod.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            VerifiedMethodScreen(navController = navController, vm = authViewModel)
        }
        composable(route = AppDestination.VerifiedOtp.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            VerifiedOtpScreen(navController = navController, vm = authViewModel)
        }
        composable(route = AppDestination.VerifiedQuestion.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            VerifiedQuestionScreen(navController = navController, vm = authViewModel)
        }
        composable(route = AppDestination.TwoFactor.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            TwoFactorScreen(navController = navController, vm = authViewModel)
        }

        composable(route = AppDestination.PasswordReset.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            PasswordResetScreen(navController = navController, vm = authViewModel)
        }

        composable(route = AppDestination.SuccessReset.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            SuccessResetScreen(navController = navController, vm = authViewModel)
        }

    }
}

这是我的家。

fun NavGraphBuilder.homeNavGraph(
    navController: NavHostController
) {
    navigation(
        startDestination = AppDestination.Home.route,
        route = Routes.HOME_ROUTE
    ) {
 //user
        composable(route = AppDestination.UserProfile.route + "/{${ArgsConstants.USER_PROFILE_KEY}}",
            arguments = listOf(
                navArgument(
                    name = ArgsConstants.USER_PROFILE_KEY,
                ) {
                    type = NavType.LongType
                }
            )) {

            Timber.tag("ahahah").d(it.arguments?.getLong(ArgsConstants.USER_PROFILE_KEY).toString())
            UserProfileScreen(
                navController = navController,
                friendId = it.arguments?.getLong(ArgsConstants.USER_PROFILE_KEY) ?: -1L
            )
        }
    }
}

当导航路由启动时,这是我的错误。

 java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/user_profile_screen/1084 } cannot be found in the navigation graph NavGraph(0x78dcd1ef) route=root startDestination={Destination(0xf2da2703) route=branding_screen}

我已经在其他项目中实现了导航参数,但是在这个项目中,我管理了3个图。我认为我的失败是因为这个。我尝试了其他方式,例如与ViewModel中的SavestateHandle共享。并且也失败。请帮我。我呆在这个星期里。

I want to pass {id} from ListScreen to DetailScreen. In ListScreen, when a click event is occured, I start navigate to DetailScreen like this.

navController.navigate(
                        route = AppDestination.UserProfile.passId(
                            friendId = it.friendId
                        )
                    )

In DetailScreen, I get that friendId through constructor like this.

@Composable
fun UserProfileScreen(
    navController: NavController,
    friendId: Long,
) {
    UserProfileView(
        navController = navController,
        friendId = friendId
    )
}

In my app, I just manage navigation flow with 3 graphs. Like RootGraph, AuthGraph and HomeGraph. Following is the navigation codes.

object Routes {
    const val AUTH_ROUTE = "auth"
    const val HOME_ROUTE = "home"
    const val ROOT_ROUTE = "root"
}

object ArgsConstants{
    const val USER_PROFILE_KEY = "id"
}

sealed class AppDestination(val route: String) {
 //user
    object UserProfile : AppDestination(route = "user_profile_screen/{${ArgsConstants.USER_PROFILE_KEY}}"){
        fun passId(friendId : Long): String{

            return this.route.replace(
                oldValue = "{${ArgsConstants.USER_PROFILE_KEY}}",
                newValue = friendId.toString()
            )
        }
    }
}

This is my RootGraph.

@Composable
fun RootNavGraph(
    navController: NavHostController
) {
    NavHost(
        navController = navController,
        startDestination = AppDestination.Branding.route,
        route = Routes.ROOT_ROUTE
    ) {
        composable(route = AppDestination.Branding.route) {
            BrandingScreen(navController = navController)
        }

        authNavGraph(navController = navController)
        homeNavGraph(navController = navController)

    }
}

This is my AuthGraph.

fun NavGraphBuilder.authNavGraph(
    navController: NavHostController
) {
    navigation(
        startDestination = AppDestination.Language.route,
        route = Routes.AUTH_ROUTE
    ) {

        composable(route = AppDestination.Language.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            LanguageScreen(navController = navController, vm = authViewModel)
        }

        composable(route = AppDestination.Login.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            LoginScreen(navController = navController, vm = authViewModel)
        }

        composable(route = AppDestination.Signup.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            SignupScreen(navController = navController, vm = authViewModel)
        }

        composable(route = AppDestination.VerifiedAccount.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            VerifiedAccountScreen(navController = navController, vm = authViewModel)
        }
        composable(route = AppDestination.NoAccount.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            NoAccountScreen(navController = navController, vm = authViewModel)
        }
        composable(route = AppDestination.VerifiedMethod.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            VerifiedMethodScreen(navController = navController, vm = authViewModel)
        }
        composable(route = AppDestination.VerifiedOtp.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            VerifiedOtpScreen(navController = navController, vm = authViewModel)
        }
        composable(route = AppDestination.VerifiedQuestion.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            VerifiedQuestionScreen(navController = navController, vm = authViewModel)
        }
        composable(route = AppDestination.TwoFactor.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            TwoFactorScreen(navController = navController, vm = authViewModel)
        }

        composable(route = AppDestination.PasswordReset.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            PasswordResetScreen(navController = navController, vm = authViewModel)
        }

        composable(route = AppDestination.SuccessReset.route) {
            val parentEntry = remember {
                navController.getBackStackEntry(Routes.AUTH_ROUTE)
            }
            val authViewModel = hiltViewModel<AuthViewModel>(parentEntry)

            SuccessResetScreen(navController = navController, vm = authViewModel)
        }

    }
}

This is my HomeGraph.

fun NavGraphBuilder.homeNavGraph(
    navController: NavHostController
) {
    navigation(
        startDestination = AppDestination.Home.route,
        route = Routes.HOME_ROUTE
    ) {
 //user
        composable(route = AppDestination.UserProfile.route + "/{${ArgsConstants.USER_PROFILE_KEY}}",
            arguments = listOf(
                navArgument(
                    name = ArgsConstants.USER_PROFILE_KEY,
                ) {
                    type = NavType.LongType
                }
            )) {

            Timber.tag("ahahah").d(it.arguments?.getLong(ArgsConstants.USER_PROFILE_KEY).toString())
            UserProfileScreen(
                navController = navController,
                friendId = it.arguments?.getLong(ArgsConstants.USER_PROFILE_KEY) ?: -1L
            )
        }
    }
}

This is my error when navigate route is launch.

 java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/user_profile_screen/1084 } cannot be found in the navigation graph NavGraph(0x78dcd1ef) route=root startDestination={Destination(0xf2da2703) route=branding_screen}

I have implemented navigation arguments in other projects but in this project, I manage 3 graphs. I think my failure is because of this. I tried other ways like shared with saveStateHandle in ViewModel. and also fail. Please help me. I stuck in this a week.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文