I have an issue with a common ViewModel and navigation in my Compose Multiplatform application
meet2602 opened this issue · 3 comments
Describe the bug
I have an issue with a common ViewModel and navigation in my Compose Multiplatform application. The ViewModel is initialized in the common main:
val headlineViewModel = viewModel { HeadlineViewModel() }
I use two NavHost components for navigation:
@Composable
fun RootNavGraph() {
val rootNavController = rememberNavController()
NavHost(
navController = rootNavController,
route = Graph.RootGraph,
startDestination = Graph.MainScreenGraph,
) {
composable(route = Graph.MainScreenGraph) {
MainScreen(rootNavController)
}
composable(route = NewsRouteScreen.NewsDetail.route) {
rootNavController.previousBackStackEntry?.savedStateHandle?.get<String>("article")?.let { article ->
val currentArticle: Article = Json.decodeFromString(article)
ArticleDetailScreen(rootNavController, currentArticle)
}
}
}
}
@Composable
fun MainNavGraph(
rootNavController: NavHostController,
homeNavController: NavHostController = rememberNavController(),
innerPadding: PaddingValues,
) {
NavHost(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding),
navController = homeNavController,
route = Graph.MainScreenGraph,
startDestination = MainRouteScreen.Headline.route,
) {
composable(route = MainRouteScreen.Headline.route) {
HeadlineScreen(rootNavController)
}
composable(route = MainRouteScreen.Search.route) {
SearchScreen(rootNavController)
}
composable(route = MainRouteScreen.Bookmark.route) {
BookmarkScreen(rootNavController)
}
}
}
When navigating from the main screen to the detail screen:
navController.navigate(NewsRouteScreen.NewsDetail.route)
and then back to the main screen:
navController.navigateUp()
the MainNavGraph
resets to the default start destination (MainRouteScreen.Headline.route
). This causes the ViewModel to be recreated and any navigation state or position within the MainNavGraph
is lost. How can I prevent the MainNavGraph
from resetting and preserve the navigation state when navigating back?
Affected platforms
- Android
- Desktop (Windows, Linux, macOS)
- iOS
Versions
compose-plugin = "1.6.11"
kotlin = "2.0.0"
lifecycleViewmodel = "2.8.2"
navigationCompose = "2.8.0-alpha02"
Additional context
I also tried using Koin in Android with viewModelOf
and on other platforms with singleOf
, and it works perfectly.
I'm having same issue. On my app, I have a bottom navigation bar, which leads to different screens, each with its own viewModel.
Every time I navigate to one of the screens, a new viewModel is created for that screen.
This issue is happening either on Android or IOS... with iOS I understand it still needs some work, as the lifecycle is different than Android. But I'm concerned why Android is having this issue as well.
The problem here is in unsupported restoring (de/serialization) of NavHostController
outside of Android. It's tracked in #4735
Workaround 1: Use single NavHostController and define nested graphs via NavGraphBuilder.navigation() function. See documentation
Workaround 2: Move second rememberNavController() call out of wiped composition.
Closing as duplicate
But I'm concerned why Android is having this issue as well.
It's clearly a separate one. If it doesn't work on Android - it's not an issue for this fork, please report the bug to Google.
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.