Shashank
09/13/2020, 5:57 PMStateFlow
by asserting the list of values received by it.
data class State(val isLoading: Boolean, val name: String?)
fun main() {
val mutableStateFlow = MutableStateFlow(State(false, null))
val stateFlow = mutableStateFlow as StateFlow<State>
val scope1 = CoroutineScope(Job())
val scope2 = CoroutineScope(Job())
scope1.launch {
delay(1000)
mutableStateFlow.value = State(true, null)
mutableStateFlow.value = State(false, "name")
}
scope2.launch {
stateFlow.collect {
println("value = $it")
}
}
Thread.sleep(2000)
}
Here is my code. Instead of getting State(true, null)
as the second value, I only receive the initial value and the last value (State(false, name)
)araqnid
09/13/2020, 6:00 PMdelay(10)
between the two writes to mutableStateFlow.value
showed the intermediate state. Presumably it’s a race condition, the intermediate state is being overwritten before it’s been publishedyield()
is enough on my test machineZach Klippenstein (he/him) [MOD]
09/13/2020, 6:07 PMStateFlow
conflates such values, so the intermediate value will never be seen. Steve’s suggestions add a suspend point between the two calls, which gives your collector a chance to resume.val finishLoad = Job()
…
mutableStateFlow.value = State(true, null)
finishLoad.join()
mutableStateFlow.value = State(false, "name")
…
assertEquals(State(true, null), collectingChannel.receive())
assertTrue(collectingChannel.isEmptyForReceive)
finishLoad.complete()
assertEquals(State(false, "name"), collectingChannel.receive())
assertTrue(collectingChannel.isEmptyForReceive)
Adam Powell
09/13/2020, 6:16 PMShashank
09/13/2020, 7:06 PMZach Klippenstein (he/him) [MOD]
09/13/2020, 8:33 PMShashank
09/13/2020, 10:35 PMState, by nature, doesn’t matter if you conflate it. If you start out in state A, then end up in state C, it doesn’t matter if there was a state B in the middle there somewhereWell, doesn’t this make testing a bit difficult? Let’s say I set
state = State(false, emptyList)
. Then I call a function which sets state = State(true, emptyList)
. The state flow will only give me the second value if there is very little time difference between the two.
So wouldn’t I need to know about the implementation of my SUT and know at which points is the state set without any dealy?your best option is to use BroadcastChannel for events.I don’t think it re-emits the latest value to new subscribers. So I can’t really use it for my view state stream.
Adam Powell
09/13/2020, 11:06 PMZach Klippenstein (he/him) [MOD]
09/13/2020, 11:35 PMAnvith
09/14/2020, 3:49 AMAdam Powell
09/14/2020, 1:48 PMAnvith
09/15/2020, 5:10 AM