Natalia Chuzhmarova
09/07/2022, 7:49 AMfun data(): Flow = flowOf(
flowOf(cachedValue),
networkCallFlow
). flattenConcat()
which is then observed in a ViewModel and mapped to UI state
data()
.onEach { .. }
.map { uiState(data) }
.catch { emit(uiState(error)) }
It works fine when the network call succeeds. The problem is, when networkCallFlow throws an exception (no network), the cachedValue is never mapped, however it triggers the onEach handler. My guess is that the emission of the cachedValue does not guarantee that it will be observed, and the exception halts the Flow before the consumption of the cachedValue happens or while it is in progress.
Is my understanding correct?
Is there any way to adjust the Flow to fit the requirements?
The code: https://pl.kotl.in/3U8jVprL-ephemient
09/07/2022, 8:19 AMflowOf(
flowOf(1),
flow { TODO() }
)
.flattenConcat()
.map { "value=$it" }
.catch { emit("error=$it") }
.collect { println("collect($it)") }
this prints out
collect(value=1)
collect(error=kotlin.NotImplementedError: An operation is not implemented.)Francesc
09/07/2022, 6:54 PMonStartNatalia Chuzhmarova
09/07/2022, 11:46 PMNatalia Chuzhmarova
09/08/2022, 1:21 AMephemient
09/08/2022, 1:41 AMCoroutineScope like that is not good, but that's unrelated
made a much smaller reproducible case which makes the behavior more obvious:
suspend fun main() {
do {
val list = flow { emit(1); TODO() }.flowOn(<http://Dispatchers.IO|Dispatchers.IO>).catch { emit(0) }.toList()
println(list)
} while (list == listOf(1, 0))
}ephemient
09/08/2022, 1:42 AMephemient
09/08/2022, 1:45 AM.flowOn because with the flow and collector running in lockstep, the flow suspends when emittingNatalia Chuzhmarova
09/08/2022, 1:55 AMnetworkCallFlow so that the resulting observed Flow never throws anything.ephemient
09/08/2022, 2:00 AMNatalia Chuzhmarova
09/08/2022, 2:03 AMephemient
09/08/2022, 2:03 AMNatalia Chuzhmarova
09/08/2022, 2:04 AM