I am on an Android project using Kotlin and Flows. My team wants to handle non-nominal cases by throwing exceptions. If a class uses a MutableStateFlow, using it to expose a Flow, how can an exception be emitted to that MutableStateFlow so that the consumer can 'catch' and act on the exception? (Is this approach even possible?)
For a code example.
method2().catch{
// How can I catch an exception thrown from evaluateEnvStatus?
}.collect {
// ....
}
val mutableSharedFlow = MutableSharedFlow<String>()
suspend fun evaluateEnvStatus(){
if(isEnvAcceptable){
mutableSharedFlow.emit("Acceptable")
else {
// How can I throw an exception here that can be caught by someone consuming the SharedFlow?
}
}
fun updateEnvStatus : Flow<String> {
scope.launch(){
method1()
}
return mutableSharedFlow
}
You can't "throw" an exception from SharedFlow because that would mean it completed and SharedFlows never end.
If you want to emit failure to collectors you have to instead expose a cold flow that transforms value of your shared flow and throws then.
For example:
private val _messageFlow = MutableSharedFlow<Result<String>>()
val messageFlow = _messageFlow.map { it.getOrThrow() }
// where you produce values:
private suspend fun evaluateEnvStatus(){
if(isEnvAcceptable){
_messageFlow.emit(Result.success("Acceptable"))
} else {
_messageFlow.emit(Result.failure(IllegalArgumentException("Unacceptable")))
}
}
// collecting:
// to stop collecting on exception catch it
messageFlow
.catch { exception -> } // handle exception
.collect { message -> } // String
// to keep collecting after exception, retry the cold flow *
messageFlow
.retry { exception -> true } // handle exception and return true
.collect { message -> } // String
Do note that retrying has a big caveat: even though you will restart the flow collection, any values emitted between exception and restart won't be handled and so will be values in buffer (if you enable it). So I would not actually recommend it for this case.
If you really need to collect all values I don't think there's a better solution to just emitting a wrapped error and parsing it on collector side without using any exception handling.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With