what is the best way for viewmodel to subscribe to...
# compose
d
what is the best way for viewmodel to subscribe to data flows?:
Copy code
LaunchedEffect(Unit) { vm.fetchAllData() } // 1

val uiState = vm.ui.collectAsStateWithLifecycle() // 2 (but we must combine all flows in a single state which is a complex logic)

init { viewModelScope.launch { fetchAllData().collect { ... }}} // 3 subscribing inside vm constructor (but this didn't respect 
compose lifecycle)

??? // 4 any better alternative?
👀 1
g
[Android documentation](https://developer.android.com/kotlin/flow?hl=pt-br#collect) uses approach #3, but I personally don't like it for the same reason you wrote. I use it, but I don't like. I've seen codes using
flow.stateIn(scope, SharingStarted.WhileSubscribed, initialValue)
instead, but it is basically the same thing but in the property directly instead of the
init
block but "safer" because of the
WhileSubscribed
This article talks about it more in depth: https://medium.com/adidoescode/the-viewmodels-leaked-flow-collectors-problem-239a327f4b56
d
thanks I'm thinking about the case where we have like
7
parallel data flows, some of them are interdependent... Each having it's own collectAsState would be handy, but this is viewmodel layer and I don't want to expose them to UI. I need some place to put all my parallel collections and they should be compose-aware at the same time.
the basic
.onStart() / .onStop()
in viewmodel would solve this, but then again I have to track and cancel
job
s myself
g
combine
does not work? You combine the 7 flows in only one and expose it to the UI.
d
yep, doing something like this it's not a simple combine tho 🙂 more like a graph
maybe some islands of this graph can have their own state, but its not the ui state, it is data layer
g
Then I'd use the
onStart/onStop
as you said. But only because I can't think another way and I don't know the full context of it. But if you find another approach, comment here please.
p
I also do
onStart/onStop
event from LifeCycleEvent Composable. Like the traditional Activity/Fragment way. Sorry Google but I still don't buy
2
3
is bad for unit test, it mess them up really bad. Introduces race conditions where sometimes the test passes sometimes doesn't, makes it a Flaky test. The onStart/onStop, has a little caveat when the Composable is hosted in a LazyList. The LazyList will call onStart/onStop when the Composable goes off the ViewPort and when it enters back. To avoid that you will have to create your own workaround