https://kotlinlang.org logo
#compose
Title
# compose
y

YASAN

10/26/2021, 9:10 PM
I am using Compose navigation for my app. I have 3 screens: A, B (dynamic) & C (dynamic). The user can navigate to a new C screen from all 3 screens but I want there to be only 1 C screen. so anytime a new version is navigated to, the old C should be removed from back stack. Can anyone help me how I can achieve that? I have tried a few things but none worked properly
Note that B & C have dynamic routes which contains some id them. Any help would be great. I know it might be too simple but I couldnt figure it out 😕
d

darkmoon_uk

10/26/2021, 9:24 PM
Apologies for not answering your question directly; but it may be helpful to consider not using Compose Navigation at all? I assume you're referring to the Jetpack Navigation integration with Compose. After some experience with different navigation mechanisms, it appears to me that Jetpack Navigation integration with Compose can be an unfortunate honeypot that leads people into thinking that's just 'how you do navigation' with Compose. It isn't so. I think all but the most complex cases can be served in the simplest way: by making the 'screen' that are you are just a high-level branch of the same
@Compose
-able declaration.
Most of the time this approach elides much more nicely with Compose; the idea of an imperative back-stack kind of clashes with Compose's declarative philosophy. Jetpack Navigation has its use when retrofitting Compose to an existing project that's already heavily architected around the Stack concept, otherwise declarative feels simpler and more sustainable to me.
To illustrate, your top level
@Composable
might include something like:
Copy code
val screen by myNavViewModel.screenFlow.collectAsState()
when(screen) {
   Screen.A -> screenAContent(screenAViewModel)
   Screen.B -> screenAContent(screenBViewModel)
   ... etc.
}
...perhaps all inside an
AnimatedContent
block to effect transition animations etc.
It sounds like breaking free from Jetpack Navigation's back-stack can really address your use-case too: you're free to implement a stack of
Screen
if you want, or any other custom logic.
y

YASAN

10/26/2021, 9:40 PM
I understand what youre saying but it does not really answer my question 🤔 I know it can be achieved in other ways but I am pretty sure it should be possible with the compose navigation library since is a simple backstack pop.
i

Ian Lake

10/26/2021, 9:43 PM
If you add
popUpTo("c/${id}") { inclusive = true }
to your
navigate
call then it'll pop everything between your current destination and the previous copy of C. That does nothing if C isn't on the stack at all, so it is safe to call every time you navigate to your new C
🙌 1
It is a stack in every sense of the word though, so if you were A - > C -> B and then popUpTo C while navigating to C, you would get A -> C'
y

YASAN

10/26/2021, 10:02 PM
Thanks it works as I wanted! I actually had tried this before but my mistake was that I put actual variables inside the
popUpTo
route param and didnt put it like
${id}
.
i

Ian Lake

10/26/2021, 10:04 PM
It needs to match the
route
String exactly, character by character
🙌 1
d

darkmoon_uk

10/26/2021, 10:04 PM
Can you ever have C, A, B on your stack? It sounds like that is possible from your description. If so, then would you need logic to re-push A and B?
y

YASAN

10/26/2021, 10:08 PM
Not really. C does not let the user to get to A/B unless you go back.
I am not sure what you mean by repushing A and B really
d

darkmoon_uk

10/26/2021, 10:11 PM
If C is always the last screen on the stack, then it sounds like you have your solution 👍 (That wasn't clear to me from description).
i

Ian Lake

10/26/2021, 10:11 PM
Note that there's another flag,
launchSingleTop
that lets you specifically avoid multiple repeated copies of C on the top of the stack if you know there's never going to be anything on top of C
🙌 1
So you get to choose if you want to pop everything back to C no matter where it is on the stack (global unique) or if you only care about repeats on the top (local unique)
y

YASAN

10/26/2021, 10:18 PM
My app is actually 5 pages and C is not always on top. but you can only get to C from A & B so I am pretty sure the backstack pop will work properly.
I do always want a single instance of C but I dont want to reuse the old data if my C id is different
i

Ian Lake

10/26/2021, 10:20 PM
Yep, sounds like
popUpTo
is exactly the right tool then
🙌 1
l

Lucien Guimaraes

10/26/2021, 11:01 PM
About compose navigation, I have a specific use case I'm also struggling with. Here is my use case: a bottomBar with 3 tabs, the last tab can display screen C (user not logged) or screen D (user logged). Screen C is a nested graph with all the login screens. In my HomeViewModel I expose if the user is logged or not and it's forwarded to the login nested graph (updating the startDestination) When user successfully signIn, I want to navigate to screen D and clearing the backstack, to avoid having login screens when user click on back button. How to do so properly?
i

Ian Lake

10/26/2021, 11:03 PM
Lucien, I'd avoid co-opting someone else's thread and instead start your own for a completely different question, it'll make it a lot easier to track 🙂
l

Lucien Guimaraes

10/26/2021, 11:12 PM
Sorry, I will do it!