In navigation component, when i navigate to differ...
# compose
s
In navigation component, when i navigate to different composable. My previous composable is still observing state changes. Shouldn't the scope of the composable stop observing?
s
Composable become part of the backstack if you navigate to other Composable, its ViewModel remains alive. but if you pop back from Composable it will destroy it's ViewModel.
s
Thanks for the information, any documentation regarding this? Also, being lazy instead of searching asking you, maybe if there is a way to just observe/collect a publisher only when composable is visible ? something like what we used to do in fragments
Copy code
lifecycleScope.launchWhenResumed {
            viewModel.getData().collect {
                // ...
            }
m
@shahroz
Flow.flowWithLifecycle
is solution for what you need
s
Thanks @Marko Novakovic let me give it a shot.
m
let me know if that solved your problem
s
@Marko Novakovic I keep on getting
Copy code
Unresolved reference: flowWithLifecycle
Do you have any clue what dependency i might be missing? got all of the lifecyle ones as well as compose lifecycle one
Nevermind, its not present in the stable version but 2.4.0-alpha03.
m
does it work for you?
s
You can use DisposableEffect or LaunchEffect if you want to call suspend function, When Composable is visible.
m
that can be done but you would need
subscribe
and
dispose
type of scenario,
flowWithLifecycle
provides that without boilerplate
a
Navigation doesn't keep other destinations composed while they're on the back stack, just collectAsState will stop when you navigate away
i
With the caveat that you will still be composing while you are animating out (you're still visible, so yeah, you're going to still be composed)
1
s
Yeah i am actually using
collectAsState
but it still keep the previous destination compose. I have tried to separate the view models for the both composable methods as well, but even then last destination keeps on collecting. Tried
flowWithLifecycle
as recommended by Marko and https://medium.com/androiddevelopers/a-safer-way-to-collect-flows-from-android-uis-23080b1f8bda the composable still collects the state changes.
a
Could you share some code that's behaving this way? That doesn't sound right
s
I'll try to replicate it with dummy/sample code and share with you. But even i am surprised as to why this is happening
@Adam Powell found the issue, i was doing this wrong
Copy code
You should only call navigate() as part of a callback and not as part of your composable itself, to avoid calling navigate() on every recomposition.
https://developer.android.com/jetpack/compose/navigation But whats the solution for it? for example, i want to navigate on state change? Example: You click on "Groups" tab, we fetch the groups from API, and if there is a group present you are a part of, I want to navigate the user to that particular group screen, otherwise just show the listings of the groups. This way, you will be on your group screen and if you navigate back, you are back to group listing screen. Whats the best approach to handle such thing?
i
navigate()
is a side-effect, so you should be using the APIs for handling side effects: https://developer.android.com/jetpack/compose/side-effects - i.e.,
LaunchedEffect(groupToLaunch) { navController.navigate("group/$groupToLaunch") }
But really, you want to have that information before you click on the 'Groups' tab - that way your 'navigate to the groups tab' can just conditionally call
navigate()
a second time. This would add the 'Groups' screen to the back stack, but run the right animation between whatever screen you're on directly to the group detail screen
s
Thanks Ian, I agree with your second suggestion but i wanted to keep my app navigations light, and just passing lambda functions to composables and let the view-models/repositories do the heavy lighting and compose just update view states. I'll check if i can make it more robust and flexible.