У меня есть следующий запрос:
@POST("devices/link/")
fun linkDevice(
@Body deviceInfo: DeviceInfo
): Single<Response<UserDevice>>
Я хочу добиться следующего:
Если запрос был успешным, получить DeviceInfo и, в зависимости от кода состояния, сообщить о событии аналитикам
Если запрос не удался, получите исключение, преобразуйте его и перебросьте.
Итак, код:
fun linkDevice(): Single<UserDevice> {
val deviceInfo = deviceUtil.getDeviceInfo()
return devicesService
.linkDevice(deviceInfo)
.onErrorResumeNext { e ->
val transformedException = transformRequestException(e) { httpException ->
return@transformRequestException when (httpException.code()) {
409 -> DeviceAlreadyLinkedException()
else -> null
}
}
Single.error(transformedException)
}
.flatMap { response ->
if (response.isSuccessful) {
val userDevice = response.body()
userDevice?.let {
userPreferences.setDeviceId(it.id)
}
when (response.code()) {
200 -> {
// TODO: Analytics
}
201 -> {
// TODO: Analytics
}
}
Single.just(userDevice)
} else {
throw ApiException()
}
}
}
/**
* Transform exception that came from request
* By default, handles only network and HTTP 401 exceptions, but can contain custom logic, passed with specialTransformer
*/
fun transformRequestException(
e: Throwable,
specialTransformer: ((httpException: HttpException) -> Exception?)? = null
): Exception {
return if (e is HttpException) {
if (e.code() == 401) {
NotAuthenticatedException()
} else {
specialTransformer?.invoke(e) ?: ApiException()
}
} else {
NetworkException()
}
}
Но этот код не работает, если я работаю с объектом Response, он будет работать только с Single<UserDevice>
в моем сервисе Retrofit.
Но с Single<UserDevice>
я не могу получить коды 2XX.
Итак, как реализовать желаемое поведение?