как обработать ошибку в охтт3 без сбоев - PullRequest
1 голос
/ 09 октября 2019

Я использую следующий метод для обработки моих запросов

override fun intercept(chain: Interceptor.Chain): Response = chain.proceed(chain.request())
        .let { originalResponse ->

            Log.i("AMIRA999", "code : " + originalResponse.code())

            when (originalResponse.code()) {

                200 -> {
                    Log.i("AMIRA999", "body : " + getErrorResponse(originalResponse))
                    originalResponse
                }
                401, 404 -> {


                    Log.i("AMIRA999", "body : " + getErrorResponse(originalResponse))
                    originalResponse

                    /*return originalResponse.mapToBody(
                        originalResponse.body()?.contentType(),
                        getErrorResponse(originalResponse)
                    )*/
                }
                else -> {
                    Log.i("AMIRA999", "body : " + originalResponse.body().toString())
                    throw BadRequestException()
                }
            }
        }

метод отлично работает, когда код равен 200, но сбой, если код 404 или 401

что янеобходимо продолжать возвращать json с сервера и не дает сбой, чтобы иметь возможность обработать его с сообщением об ошибке

как я могу это сделать?

полученное аварийное завершение следующее

retrofit2.HttpException: HTTP 401 UNAUTHORIZED
at com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory$BodyCallAdapter$adapt$2.onResponse(CoroutineCallAdapterFactory.kt:104)
at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:129)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:206)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)

Ответы [ 2 ]

1 голос
/ 09 октября 2019

Вы используете retrofit2-kotlin-coroutines-adapter , и исключение выбрано специально. Любой не-1005 * HTTP-ответ, такой как 401, вызовет исключение. Вы можете сами убедиться в этом в библиотеке исходный код

if (response.isSuccessful) {
  deferred.complete(response.body()!!)
} else {
  deferred.completeExceptionally(HttpException(response))
}

Но это не проблема. Вы по-прежнему можете получить доступ к ответу и своему JSON, выполнив catch (e: HttpException), а затем позвонив val yourJson = e.response()?.body() as? YourJson.

Обратите внимание, что retrofit2-kotlin-coroutines-adapter устарел и что вы должны перейти на Retrofit 2.6.0 или новее. Затем вы можете добавить к своим интерфейсным функциям *1022* Retrofit , чтобы вы могли написать хороший идиоматический код Kotlin.

0 голосов
/ 09 октября 2019

Retrofit 2 имеет другую концепцию обработки "successful" запросов, чем Retrofit 1. В Retrofit 2 все requests, которые могут быть выполнены (отправлены в API) и для которых вы получаете response, рассматриваются как "successful". Это означает, что для этих requests вызывается обратный вызов onResponse, и вам нужно вручную проверить, действительно ли request successful (status 200-299) или erroneous (status 400-599).

Если запрос завершен successfully,мы можем использовать response object и делать все, что захотим. Если error на самом деле failed (remember, status 400-599), мы хотим показать пользователю соответствующую информацию о проблеме.

Пример

Error Object

Предположим, ваш API отправляет JSON error body следующим образом:

{
    statusCode: 409,
    message: "Email address already registered"
}

Примечание: вы можете увидеть JSON error body, напечатав response.errorBody()

Чтобы избежать такого плохого взаимодействия с пользователем, мы сопоставляем тело ответа с объектом Java, представленным следующим классом.

class APIError {
  private val statusCode:Int = 0
  private val message:String
  fun status():Int {
    return statusCode
  }
  fun message():String {
    return message
  }
}

Error Handler

object ErrorUtils {
  fun parseError(response:Response<*>):APIError {
    val converter = ServiceGenerator.retrofit()
    .responseBodyConverter(APIError::class.java, arrayOfNulls<Annotation>(0))
    val error:APIError
    try
    {
      error = converter.convert(response.errorBody())
    }
    catch (e:IOException) {
      return APIError()
    }
    return error
  }
}

Error Handler in Action

Теперь вы можете обрабатывать error в API response, используя ErrorUtils, как показано ниже.

val call = service.me()
call.enqueue(object:Callback<User>() {
  fun onResponse(call:Call<User>, response:Response<User>) {
    if (response.isSuccessful())
    {
      // use response data and do some fancy stuff :)
    }
    else
    {
      // parse the response body …
      val error = ErrorUtils.parseError(response)
      // … and use it to show error information
      // … or just log the issue like we’re doing :)
      Log.d("error message", error.message())
    }
  }
  fun onFailure(call:Call<User>, t:Throwable) {
    // there is more than just a failing request (like: no internet connection)
  }
})

Полный пример с видео приведен здесь retrofit-2-error-processing .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...