Kotlin и модернизация: как обрабатывать ответы HTTP 400? - PullRequest
0 голосов
/ 09 января 2020

Я использую Retrofit (2.6) на Android для реализации службы, которая подключается к веб-серверу и запрашивает, чтобы сервер предпринял некоторую работу. Соответствующий код можно обобщить следующим образом:

interface MyService {
    @GET(START_WORK)
    suspend fun startWork(@Query("uuid") uuid: String,
                          @Query("mode") mode: Int):
        MyStartWorkResponse
}

// Do some other things, include get a reference to a properly configured
// instance of Retrofit.

// Instantiate service
var service: MyService = retrofit.create(MyService::class.java)

Я могу без проблем позвонить service.startWork() и получить действительные результаты. Однако в некоторых случаях веб-сервер возвращает код ошибки 400 с телом ответа, в котором указана c информация об ошибке. Однако запрос не искажен; просто есть еще одна проблема, на которую следует обратить внимание пользователя. Проблема в том, что я не могу сказать, в чем проблема, потому что я не получаю ответ; вместо этого мой вызов вызывает исключение из-за кода ошибки 400.

Я не понимаю, как изменить свой код, чтобы я мог перехватить и обработать 400 ответов об ошибках и получить необходимую информацию из тела ответа. Это работа сетевого перехватчика на моем клиенте okhttp? Кто-нибудь может пролить свет?

Ответы [ 2 ]

1 голос
/ 09 января 2020

Используйте этот код (KOTLIN)

class ApiClient {

companion object {

private val BASE_URL = "YOUR_URL_SERVER"
private var retrofit: Retrofit? = null

private val okHttpClientvalor = OkHttpClient.Builder()
    .connectTimeout(90, TimeUnit.SECONDS)
    .writeTimeout(90, TimeUnit.SECONDS)
    .readTimeout(90, TimeUnit.SECONDS)
    .build()

fun  apiClient(): Retrofit {

    if (retrofit == null) {
        retrofit = Retrofit.Builder().baseUrl(BASE_URL)
            .client(okHttpClientvalor)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }
    return retrofit!!
}

}

}

object ErrorUtils {

fun parseError(response: Response<*>): ErrorResponce? {
    val conversorDeErro = ApiClient.apiClient()
        .responseBodyConverter<ErrorResponce>(ErrorResponce::class.java, arrayOfNulls(0))
    var errorResponce: ErrorResponce? = null
    try {
        if (response.errorBody() != null) {
            errorResponce = conversorDeErro.convert(response.errorBody()!!)
        }
    } catch (e: IOException) {
        return ErrorResponce()
    } finally {
        return errorResponce
    }
}

}

class ErrorResponce {
 /*This name "error" must match the message key returned by the server.
  Example: {"error": "Bad Request ....."}*/
@SerializedName("error")
@Expose
var error: String? = null

}

if (response.isSuccessful) {
    return MyResponse(response.body()//transform
            ?: //some empty object)
} else {
        val errorResponce = ErrorUtils.parseError(response)
        errorResponce!!.error?.let { message ->
        Toast.makeText(this,message,Toast.LENGTH_SHORT).show()
     }
}
0 голосов
/ 09 января 2020

Модернизация определяет успешный ответ следующим образом:

publi c boolean isSuccessful () {код возврата> = 200 && code <300; } </p>

, что означает, что вы должны быть в состоянии сделать что-то вроде этого

class ServiceImpl(private val myService: MyService) {
   suspend fun startWork(//query): MyResponse =

    myService.startWork(query).await().let {

    if (response.isSuccessful) {
        return MyResponse(response.body()//transform
                ?: //some empty object)
    } else {
        throw HttpException(response)//or handle - whatever
    }
}

}
...