miqbaldc
04/22/2021, 9:06 AMval state = MutableStateFlow(...)
state.map {
// a reducer
}.catch {
// catch the exception happened in a reducer
}
suggestion:
reduce {
// omitted
}.catch {
when (exception) {
// to distinguish between stateA & stateB exception, unless it's a general toast
ExceptionFromStateA -> state.copy(a = // do something with data specific to stateA)
ExceptionFromStateB -> state.copy(b = // similar to the above apprach)
}
// or a general error message
state.copy(errorMessage = it.message)
}
Mikolaj Leszczynski
04/22/2021, 9:55 AMtry/catch
block or Kotlin’s runCatching()
?
E.g. this works out of the box:
reduce {
runCatching {
// This returns a state or throws an exception
}.getOrElse {
// This gets called if it catches an exception
state.copy(id = 0)
}
}
The reason I’m asking is that exceptions thrown in reducers will likely be dependent on your implementation - from experience I gained on a project leaning heavily on MVI I don’t really remember a real case where a reduction would throw exceptions.
In fact - why throw an exception if you can provide a fallback state inline? Otherwise you’re splitting your reducer up into two blocks, which is not great for readability.
The sample you’re pointing to is pretty synthetic, we should probably run the op before the reduction happens.
Historically, we stepped away from a stream-like syntax on purpose to keep Orbit’s syntax clean and simple, close to vanilla coroutines. Our previous experience with RxJava based MVI wasn’t great.
TL;DR I’m not sure we need this, unless you can convince me otherwise.
cc @appmattus thoughts?miqbaldc
04/23/2021, 12:46 PMrunCatching
exist.
Our current usecase to using .catch
operator was inspired from:
pedroql/MVFlow & Ezike/Baking-App
will update the github link, still AFK 🙏
Mikolaj Leszczynski
04/23/2021, 12:54 PMmiqbaldc
04/23/2021, 1:00 PMintent { }
cmiiw @Mikolaj LeszczynskiMikolaj Leszczynski
04/23/2021, 1:07 PMmiqbaldc
04/26/2021, 1:11 AMfun loadDataForId(id: Int) = intent {
postSideEffect(MySideEffect.Toast("Loading..."))
val result = try {
repository.loadData(id)
} catch (e: NetworkException) {
postSideEffect(MySideEffect.Toast(e.code().humanizedMessage()))
null
}
reduce {
state.copy(data = result)
}
}
private fun Int.humanizedMessage() = when (this) {
404 -> "Ooops, There's no such resources exist"
400 -> "Ooops, we can't process those data"
// ... any other http error code here
else -> "OOops, something went wrong"
}
Mikolaj Leszczynski
04/26/2021, 6:43 AMmiqbaldc
04/26/2021, 6:49 AM