How do I navigate to a destination when certain co...
# compose
l
How do I navigate to a destination when certain condition is met, e.g. data is loaded?
I cannot just do
Copy code
if (dataLoaded) navController.navigate(destination)
because that will try to navigate on every recomposition
s
Sounds like a normal side effect, which means you want to use the side-effect APIs, depending on your needs. For your case, probably a LaunchedEffect, keyed on said data.
Copy code
LaunchedEffect(dataLoaded) {
  if (dataLoaded) {
    navController.navigate(destination)
  }
}
l
Yes, I was thinking about something along those lines. Thank you!
t
Maybe also consider triggering navigation from your viewmodel. So there you could do the initial loading and than trigger the navigation. This would maybe also avoid reloading when navigating back or s.th. like that.
s
If you are using androidx.navigation you can not keep a reference to your NavController in your AAC ViewModel. For those cases you need to clear the state to make sure you do not re-trigger the navigation as you come back. More on this thread: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1720862935705579?thread_ts=1720811867.306169&cid=CJLTWPH7S
l
Yes, but I think not navigating through the State, but through a viewmodel callback.
t
Yea that was i meant.
l
No, it wouldn't work
You would have to keep a reference to the Composable inside the ViewModel, in order to call Navigation from the ViewModel
t
No you could use a flow with the navigation target and use this in your navigationhost as target.
s
https://medium.com/androiddevelopers/viewmodel-one-off-event-antipatterns-16a1da869b95 This article, as linked in the previously linked discussion as well explains what the caveats are with exposing such "events" as a flow/channel etc. like you suggest Timo
l
I usually solved it by creating a
Channel
inside the viewmodel, which published "one-off" events to the Activity. Then the Activity would subscribe the the
Channel
as
Flow
and react to this.
t
Lol can you read my mind Stylianos? 😄
s
I knew you'd say it yes 😄
t
wow
s
Take a look at the linked article as well Lukasz then, to make sure you understand what risks you are taking doing what you are describing.
thank you color 1
l
I think the source of misunderstanding is the dualism of Compose regarding navigation: everything in Compose is a state, but navigation is an action
s
Yeah, and you can potentially drop the event in some specific scenarios when you do this handoff from the VM to the UI if you do not treat it as state. The article explains it I think quite well.
l
Yes, the article is great. Thanks for the recommendation!
🦠 1
c
"navigation is an action" isn't always true i guess. like. on a tablet, I'll change some state, and maybe on the tablet it'll show a modal or add some composable to the screen. while on a phone it might actually navigation elsewhere. see this for warnings about channel being an anti pattern
👍 1
l
I mean in Compose Navigation the navigation is an action. You call
navController.navigate(destination)
. This is imperative, not declarative. It's not rendering state.