Is there a way to suspend while waiting for the next value of a MutableStateFlow?
val state = MutableStateFlow<Int>(1)
launch(Dispatchers.Default) {
var counter = 1
while (true) {
state.emit(counter++)
delay(1000)
}
}
launch(Dispatchers.Default) {
while (state.value < 1000) {
print(state.value)
delay(250)
}
}
Currently this is printing 111122223333444... but I want it to print 1234...
Use-case: I'm building a driver; I have one coroutine that continuously read data being received from the socket which updates the connection status.
If I want to send data, I need to first check if the status is IDLE, if not, wait until the status is IDLE before writing data.
A very crude way to do it would be to do
while (state.value != 100) { delay(100) }
But this will perform poorly.
What I want to do, is when I retrieve the value from the state, it should get the last value without suspending; if the value is the correct value, break out of the loop, otherwise suspend until the value changes and only if the value is correct, break out of the while loop, otherwise continue to suspend until the value changes again.
It's possible using a mutex, unlock the mutex when writing a new value, lock the mutex when reading it again and that while loop will suspend until the value changes again, but it would be nice to use something off-the-shelf so to speak.
var counter = 1
val mutex = Mutex(locked = true)
launch(Dispatchers.Default) {
while (true) {
counter++
mutex.unlock()
delay(100)
}
}
launch(Dispatchers.Default) {
while (true) {
if (counter > 100) {
break
}
println(counter)
mutex.lock()
}
}
You are not using flow methods at all - just transform and collect the flow instead of inventing weird loops.
Or if you don't need to print each value you can suspend in one line: