Rohan Maity
02/14/2023, 3:52 PMStateFlow.collect()
is not subscribing at all. Subscription count comes ZERO even after calling collect()
I have a classes like this
class DataApi {
private val dataUpdates = MutableStateFlow<List<Data>?>(null)
fun subscribeToDataUpdates(streamId:String, coroutineScope: CoroutineScope) {
setupDatatCollection(streamId, coroutineScope)
return dataUpdates
}
private fun setupDataCollection(streamId: String, scope:CoroutineScope) {
scope.launch {
val stream = getStream(streamId) // this is suspend
merge(fetchInitialData(), registerDataUpdates(scope)).collectLatest { list ->
// TILL HERE I AM GETTING THE UPDATES
dataUpdates.emit(list) // THIS DOES NOT WORK. SUBSCRIPTION COUNT COMES 0
}
}
}
}
class DataViewModel(private val dataApi): ViewModel() {
fun loadData(streamid: String) {
viewModelScope.launch(<http://Dispatchers.IO|Dispatchers.IO>) {
dataApi.subscribeToDataUpdates(streamid, viewModelScope).collectLatest {
// I DO NOT GET UPDATES HERE EMITTED BY `dataUpdates`
}
}
}
}
I am not sure why the subscription count is ZERO even after calling collect()
In what scenario subscription count becomes ZERO. Can someone help a little bit here?Joffrey
02/14/2023, 3:55 PMemit()
call happens after the state flow has started being collected?Joffrey
02/14/2023, 3:57 PMDataApi
, you don't know which scope
you receive. So you don't know whether the launch
doing the `merge`+`collectLatest` will be executed before or after returning dataUpdates
from subscribeToDataUpdates
- it's technically concurrent, so open to racesJoffrey
02/14/2023, 3:59 PMsubscribeToDataUpdates
, so I don't know which scope it is in real life, but if it's also viewModelScope
then if my memory doesn't fail me, the launch
should be immediately run, and there is a chance you emit values to the state flow before the subscription happensRohan Maity
02/14/2023, 4:01 PMwill be executed before or after returningBut I immediately get the initialfromdataUpdates
subscribeToDataUpdates
null
value in the client class.
And after I see the list is emitted in the merge + collectLatest
So should not I get that list emitted by stateFlow given that initial value is emitted and client has called collectLatest?Rohan Maity
02/14/2023, 4:02 PMThe code you provided doesn't compile because it doesn't pass a scopeSorry I missed it here, but it actually does. Let me correct it
Rohan Maity
02/14/2023, 4:04 PMthen if my memory doesn't fail me, theI did not get this one. Could you explain this a bit more?should be immediately run, and there is a chance you emit values to the state flow before the subscription happenslaunch
Joffrey
02/14/2023, 4:07 PMI did not get this one. Could you explain this a bit more?I meant that AFAIR
viewModelScope
starts coroutines in an undispatched manner, so a viewModelScope.launch
immediately executes its body until the first suspension point, as opposed to just "queuing" the body to be executed later. This means in theory the scope.launch
in setupDataCollection
could be executed immediately, and thus before subscribeToDataUpdates
returnsRohan Maity
02/14/2023, 4:10 PM> there is a chance you emit values to the state flow before the subscription happensIn merge + collectLatest, there is function
registerDataUpdates()
that actually receive the updates from server and update the list
Even that update is getting emitted inside the merge + collectLatest {}
but dataUpdates(stateflow)
does not emit. By this point it should be subscribed right as this server update happens way later?Rohan Maity
02/14/2023, 4:22 PMas opposed to just "queuing" the body to be executed later. This means in theory theLets say if its queuing issue. Any idea how to fix this?inscope.launch
could be executed immediately, and thus beforesetupDataCollection
returnssubscribeToDataUpdates
Rohan Maity
02/16/2023, 9:23 AM