[Compose Navigation]How to avoid repeat request wh...
# compose
l
[Compose Navigation]How to avoid repeat request when screen got retained ?
Let’s say I am using navigation compose, and I have three screens : A -> B -> C, and they share a single ViewModel created in Screen A. Every time when I navigate to screen B from screen A I have to get some data from server, so in screen B I have code like this:
Copy code
LaunchEffect(Unit) {
    viewModel.getDataForScreenB()
}
it works fine until I pop back to screen B from screen C, due to the feature of
LaunchEffect
,
viewModel.getDataForScreenB()
would also be invoked once, which is not I want. So I was wondering is there any elegant way to handle this? I’ve come up with several ways, like: putting the request into some place where I navigate from A to B or every time call
getDataForScreenB()
, check if there is already some data, if so just return. But I thought either of them passes for “elegant”, so any ideas?
d
Generally if you want something to run once and once only it best go in the viewmodel. I'm generally not a fan of doing things on init in the VM tho ... so not sure what's an elegant solution that doesn't have boilerplate, commenting to track replies 🙏
e
First, about “when screen got retained”, in androidx nav, screen is not actually retained, it is kept on the backstack even though its actual ui (composable tree/fragments etc) is removed. Secondly, in your example your UI is kinda telling your VM when to load data and it seems what you want is for your UI to say instead “I am available, give me data”. In that case, you can store a
Deferred
of the data in your VM like
Copy code
val bData = myScope.async(CoroutineStart.LAZY) { ... }
and your
getDataForScreenB()
will be a simple function that
await()
’s the data. If it already exists in VM, good it’ll return it, if not, it will suspend until it is available.
l
Hi, Efeturi, maybe “retain” should be used in another scenario, but I just couldn’t find an appropriate word to describe my scenario, and I think they should be similar so I use it 😂. And appreciate your solution, looks good, never thought of coroutine has this lazy thing.