diff --git a/README.md b/README.md index 4fddd51..f569284 100755 --- a/README.md +++ b/README.md @@ -181,14 +181,15 @@ fun onSendRequest() { } ``` -Also you can add some custom `catch` handlers for `ExceptionHandler`: +Also you can add some custom `catch` handlers for `ExceptionHandler` that work as a catch in the +try/catch operator: ```kotlin fun onSendRequest() { viewModelScope.launch { exceptionHandler.handle { serverRequest() - }.catch { // Specifying a specific exception class + }.catch { // Specifying exception class // Some custom handler code false // true - cancels ErrorPresenter; false - allows execution of ErrorsPresenter }.execute() // Starts code execution in `handle` lambda diff --git a/errors/src/commonMain/kotlin/dev/icerock/moko/errors/handler/ExceptionHandlerContext.kt b/errors/src/commonMain/kotlin/dev/icerock/moko/errors/handler/ExceptionHandlerContext.kt index ae8d6ba..057e629 100644 --- a/errors/src/commonMain/kotlin/dev/icerock/moko/errors/handler/ExceptionHandlerContext.kt +++ b/errors/src/commonMain/kotlin/dev/icerock/moko/errors/handler/ExceptionHandlerContext.kt @@ -7,12 +7,11 @@ package dev.icerock.moko.errors.handler import dev.icerock.moko.errors.ErrorEventListener import dev.icerock.moko.errors.HandlerResult import dev.icerock.moko.mvvm.dispatcher.EventsDispatcher -import kotlin.reflect.KClass abstract class ExceptionHandlerContext { abstract suspend fun execute(): HandlerResult abstract fun catch( - clazz: KClass, + condition: (Throwable) -> Boolean, catcher: (E) -> Boolean ): ExceptionHandlerContext abstract fun finally(block: () -> Unit): ExceptionHandlerContext @@ -20,7 +19,10 @@ abstract class ExceptionHandlerContext { inline fun catch( noinline catcher: (E) -> Boolean ): ExceptionHandlerContext { - return catch(E::class, catcher) + return catch( + condition = { it is E }, + catcher = catcher + ) } companion object { diff --git a/errors/src/commonMain/kotlin/dev/icerock/moko/errors/handler/ExceptionHandlerContextImpl.kt b/errors/src/commonMain/kotlin/dev/icerock/moko/errors/handler/ExceptionHandlerContextImpl.kt index 3eebe36..d25c6b2 100644 --- a/errors/src/commonMain/kotlin/dev/icerock/moko/errors/handler/ExceptionHandlerContextImpl.kt +++ b/errors/src/commonMain/kotlin/dev/icerock/moko/errors/handler/ExceptionHandlerContextImpl.kt @@ -8,7 +8,6 @@ import dev.icerock.moko.errors.ErrorEventListener import dev.icerock.moko.errors.HandlerResult import dev.icerock.moko.mvvm.dispatcher.EventsDispatcher import kotlinx.coroutines.CancellationException -import kotlin.reflect.KClass private typealias Catcher = (Throwable) -> Boolean @@ -18,15 +17,16 @@ internal class ExceptionHandlerContextImpl( private val onCatch: ((Throwable) -> Unit)?, private val block: suspend () -> R ) : ExceptionHandlerContext() { - private val catchersMap = mutableMapOf, Catcher>() + private val catchers = mutableListOf Boolean, Catcher>>() private var finallyBlock: (() -> Unit)? = null + @Suppress("UNCHECKED_CAST") override fun catch( - clazz: KClass, + condition: (Throwable) -> Boolean, catcher: (E) -> Boolean ): ExceptionHandlerContext { - catchersMap[clazz] = catcher as Catcher + catchers.add(condition to catcher as Catcher) return this } @@ -43,8 +43,8 @@ internal class ExceptionHandlerContextImpl( // Don't handle coroutines CancellationException if (e is CancellationException) throw e onCatch?.invoke(e) - val isHandled = catchersMap[e::class]?.invoke(e) - if (isHandled == null || isHandled == false) { + val isHandled = isHandledByCustomCatcher(e) + if (!isHandled) { // If not handled by a custom catcher val errorValue = exceptionMapper(e) eventsDispatcher.dispatchEvent { showError(e, errorValue) @@ -55,4 +55,11 @@ internal class ExceptionHandlerContextImpl( finallyBlock?.invoke() } } + + private fun isHandledByCustomCatcher(cause: Throwable): Boolean { + return catchers + .firstOrNull { it.first.invoke(cause) } // Finds custom catcher by invoking conditions + ?.second?.invoke(cause) // If catcher was found then execute it + ?: false + } }