Yan Pujante
03/15/2021, 4:43 PMprivate val _pendingIOs = MutableStateFlow(0)
val pendingIOs: StateFlow<Int>
get() = _pendingIOs
fun createPart(): Flow<Part> = flow {
val e = coroutineScope {
withContext(Dispatchers.Main) {
<http://logger.info|logger.info>("executing in Main")
_pendingIOs.value++
try {
async(<http://Dispatchers.IO|Dispatchers.IO>) {
delay(100) // simulate io delay
Part(_nextPartId++, "xxx")
}.await()
} finally {
<http://logger.info|logger.info>("executing in Main")
_pendingIOs.value--
}
}
}
emit(e)
}
The idea being that I am updating a pendingIO state variable prior to executing any IO. The UI can then simply display a CircularProgressIndicator when said stateflow variable is > 0. Is this an acceptable way of doing things? Is there a better way? Is my flow code correct or could be simplified?jim
03/15/2021, 5:24 PMAdam Powell
03/15/2021, 6:28 PMAdam Powell
03/15/2021, 6:29 PMpendingIOs
as
var pendingIOs by mutableStateOf(0)
private set
instead if it's primarily compose code that will consume this object/data, since you'll be able to skip some other flow subscription management and the code gets simplerYan Pujante
03/15/2021, 6:31 PMAdam Powell
03/15/2021, 7:02 PMcoroutineScope {}
wrapping withContext
is redundant; `withContext`'s behavior is a superset of coroutineScope
already. async(...) { ... }.await()
is a more complicated way of saying withContext(...) {}
Adam Powell
03/15/2021, 7:03 PMcreatePart
only ever emits a single value and then terminates, it would be better expressed as suspend fun createPart(): Part
Adam Powell
03/15/2021, 7:06 PMlogger
is not thread-safe, nothing else done by createPart
's pending count tracking (regardless of whether it's a MutableStateFlow or mutableStateOf) needs to be on the main thread, so you can drop the Dispatchers.Main
switchAdam Powell
03/15/2021, 7:10 PM++
and --
atomicYan Pujante
03/15/2021, 8:01 PM++
and --
which are obviously not thread safe which is why I was running in on the Main contextAdam Powell
03/15/2021, 8:36 PM