moko-errors
Библиотека moko-errors позволяет обрабатывать и показывать ошибки на экране из общего кода.
ExceptionMappersStorage
ExceptionMappersStorage — синглтон, хранящий набор конвертеров исключений в классы ошибок, требуемые ErrorPresenter.
Регистрация простого маппера:
ExceptionMappersStorage
.register<IllegalArgumentException, StringDesc> {
"Был передан недопустимый аргумент!".desc()
}
.register<HttpException, Int> {
it.code
}
Регистрация маппера с условием:
ExceptionMappersStorage.condition<StringDesc>(
condition = { it is CustomException && it.code == 10 },
mapper = { "Произошла кастомная ошибка!".desc() }
)
Для каждого типа ошибки (кроме StringDesc, у которого уже есть значение по умолчанию) необходимо задать fallback-значение через setFallbackValue:
ExceptionMappersStorage
.setFallbackValue<Int>(520)
val throwableToIntMapper: (Throwable) -> Int =
ExceptionMappersStorage.throwableMapper()
Регистрацию можно выстраивать в цепочку:
ExceptionMappersStorage
.condition<StringDesc>(
condition = { it is CustomException && it.code == 10 },
mapper = { "Произошла кастомная ошибка!".desc() }
)
.register<IllegalArgumentException, StringDesc> {
"Был передан недопустимый аргумент!".desc()
}
.register<HttpException, Int> {
it.code
}
.setFallbackValue<Int>(520)
ExceptionHandler
ExceptionHandler реализует безопасное выполнение кода и автоматическое отображение ошибок через ErrorPresenter.
Объявление в ViewModel:
class SimpleViewModel(
val exceptionHandler: ExceptionHandler
) : ViewModel()
Привязка на платформе.
На Android в Activity или Fragment:
viewModel.exceptionHandler.bind(
lifecycleOwner = this,
activity = this
)
На iOS в ViewController:
viewModel.exceptionHandler.bind(viewController: self)
Создание экземпляра ExceptionHandler:
val exceptionHandler = ExceptionHandler<StringDesc>(
errorPresenter = errorPresenter,
exceptionMapper = ExceptionMappersStorage.throwableMapper(),
onCatch = { println("Поймано исключение: $it") }
)
Использование в ViewModel:
fun onSendRequest() {
viewModelScope.launch {
exceptionHandler.handle {
serverRequest()
}.finally {
// код после выполнения
}.execute()
}
}
Можно добавлять кастомные catch-обработчики:
fun onSendRequest() {
viewModelScope.launch {
exceptionHandler.handle {
serverRequest()
}.catch<IllegalArgumentException> {
// кастомная обработка
false // true — отменяет показ ошибки; false — позволяет ErrorPresenter показать ошибку
}.execute()
}
}
ErrorPresenter
Набор реализаций ErrorPresenter, определяющих способ отображения ошибки на платформе:
AlertErrorPresenter— показывает ошибку в alert-диалоге;ToastErrorPresenter— показывает ошибку в toast на Android (на iOS — alert-диалог);SnackBarErrorPresenter— показывает ошибку в snackbar на Android (на iOS — alert-диалог);SelectorErrorPresenter— выбирает презентер по условию.
Создание презентеров в общем коде:
val alertErrorPresenter = AlertErrorPresenter(
alertTitle = "Ошибка".desc(),
positiveButtonText = "OK".desc()
)
val toastErrorPresenter = ToastErrorPresenter(
duration = ToastDuration.LONG
)
SelectorErrorPresenter позволяет выбрать способ показа в зависимости от типа исключения:
val selectorErrorPresenter = SelectorErrorPresenter { throwable ->
when (throwable) {
is CustomException -> alertErrorPresenter
else -> toastErrorPresenter
}
}
val exceptionHandler = ExceptionHandler(
errorPresenter = selectorErrorPresenter,
exceptionMapper = ExceptionMappersStorage.throwableMapper()
)