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 initialfromdataUpdatessubscribeToDataUpdates
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.launchcould be executed immediately, and thus beforesetupDataCollectionreturnssubscribeToDataUpdates
Rohan Maity
02/16/2023, 9:23 AM