Coroutne не перехватывают кастомные исключения
Решил перевести проект с rxjava на coroutne,начал с retrofit
//кофиг ретрофита
mAuthRetrofit = Retrofit.Builder()
.baseUrl(BASE_URL_AUTH)
.client(authClient())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.build()
fun authClient() =OkHttpClient.Builder().addInterceptor { chain ->
val response = chain.proceed(chain.request())
when (response.code()) {
400 -> throw ErrorLogin()
...
}
response
}.build()
//метод из интерфейса для retrofit
@Headers("Content-Type: application/json")
@POST("auth/login")
suspend fun login(@Body body: UserBody): UserApiPojo
//сам вызов в презентере
val errorHandler = CoroutineExceptionHandler { context, exception ->
Timber.e(exception)
}
fun clickLogin() {
if (loginAndPassIsNotEmpty()) {
viewModelScope.launch(Dispatchers.IO + errorHandler) {
val result = runCatching { repository.auth.login(login, password) }
result.onSuccess { user ->
repository.auth.saveUser(user)
withContext(Dispatchers.Main + errorHandler) {
router.loginComplete()
}
}.onFailure { error ->
viewState?.let { view ->
when (error) {
is ErrorLogin -> view.showErrorLogin()
}
}
}
}
}
}
Если запрос успешный то все работает хорошо, но если я ввожу неверные данные, то у меня OkHttpClient обрабатывает данные и возращает ошибку ErrorLogin(). На rx далее без проблем перехватывал тот или Exception и далее уже в презентере выполнял те или ные действия. Почему здесь приложение крашится и ошибка не поподает ни в errorHandler ни в result.onFailure
FATAL EXCEPTION: OkHttp Dispatcher
Process: ru.exomple.app, PID: 11546
java.lang.Error: ru.exomple.app.api.error.ErrorLogin: Login or password wrong
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1173)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: ru.exomple.app.api.error.ErrorLogin: Login or password wrong
at ru.exomple.app.api.AppService$authSetupClient$1.intercept(AppService.kt:48)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:200)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
Я конечно могу убрать throw ErrorLogin() из OkHttpClient. Но мне хотелось понимать как все это работает и почему эти ошибки не ловятся.
Ответы (1 шт):
Чтобы ваши исключения ловились Retrofit-ом и передавались вызываемому коду, они должны быть унаследованы от IOException. Все другие считаются фатальными и пропускаются выше.
Вот тут была дискуссия почему так: https://github.com/square/okhttp/pull/5457
Вот тут ответ enSO: https://stackoverflow.com/a/58711127/5479247