I've got a StateFlow that doesn't seem to emit any...
# coroutines
t
I've got a StateFlow that doesn't seem to emit any values (classic StateFlow problem) I don't think this is due to object equality, but I can't figure out what's going on..
Copy code
val skuDetails: MutableStateFlow<Set<SkuDetails>> = MutableStateFlow(emptySet())
Elsewhere:
Copy code
val newSet = skuDetails.value.toMutableSet()
    newSet.addAll(skuDetailsResult.skuDetailsList.orEmpty())
    skuDetails.value = newSet
Collecting values:
Copy code
coroutineScope.launch {
       skuDetails.collect {
            Timber.i("sku details: $it") // Never called
        }
    }
Any ideas? The CoroutineScope isn't being cancelled. The new set of values != the previous set.
g
This code should work, I think only debug can help Maybe some deadlock? Maybe you have some blocking code which blocks dispatcher of you scope
t
OK, I think I'm just calling
collect
too late, and missing the emissions
Nope. I don't really understand what's going on. I am calling the 'collecting values' block from a function. If I instead move that to the class
init { }
, the StateFlow emits as expected
This works:
Copy code
init {
    skuDetails.onEach {
        Timber.i("Emitting ${it.size} sku details")
    }.launchIn(coroutineScope)
}
This doesn't:
Copy code
fun start() {
    skuDetails.onEach {
        Timber.i("Emitting ${it.size} sku details")
    }.launchIn(coroutineScope)
}

foo.start()
Even though the StateFlow isn't updated until after
start()
is called.
I'm sure there's a logical explanation, but I just don't understand what's going on here
w
You’d need to give some more context, just changing
init
to
fun start()
is trivial but clearly there’s something more tricky going on in your codebase
☝🏻 1
l
Looks like you want a SharedFlow with a replay buffer instead of StateFlow.
t
OK, I'll see if I can replicate this in Kotlin playgrounds. Hard for me to provide more context without dumping a lot of code
@louiscad why's that?
l
I don't know, I said "looks like", you know your exact use case better.
t
Can you explain why it looks that way to you?
l
Because it seems you want to get value updates that happen before collect is called.
t
Doesn't StateFlow hold the most recent value though?
l
Yes it does, and I'm pretty sure you have it.
s
@Tim Malseed are you calling the collect block from a suspend function?