如何在嵌套导航图 Jet Compose 之间传递参数
我想将{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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论