代码之家  ›  专栏  ›  技术社区  ›  artem

如何处理改装和RxJava2中的成功和失败响应?

  •  0
  • artem  · 技术社区  · 5 年前

    @POST("devices/link/")
        fun linkDevice(
            @Body deviceInfo: DeviceInfo
        ): Single<Response<UserDevice>>
    

    我希望实现以下目标:

    1. 若请求失败,则获取异常,转换它并重试。

    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> 在我的改装服务中。

    我找不到2XX代码。

    那么,如何实现期望的行为呢?

    1 回复  |  直到 5 年前
        1
  •  0
  •   artem    5 年前

    现在,我已经解决了以下问题:

    data class RequestResult<T>(
        val data: T,
        val code: Int
    )
    
    fun <T> transformResponse(response: Response<T>): Single<RequestResult<T>> {
        if (response.isSuccessful) {
            return Single.just(RequestResult(response.body()!!, response.code()))
        } else {
            throw HttpException(response)
        }
    }
    
    fun <T> transformEmptyResponse(response: Response<T>): Completable {
        if (response.isSuccessful) {
            return Completable.complete()
        } else {
            throw HttpException(response)
        }
    }
    

    fun linkDevice(): Single<UserDevice> {
        val deviceInfo = deviceUtil.getDeviceInfo()
    
        return devicesService
            .linkDevice(deviceInfo)
            .flatMap { transformResponse(it) }
            .flatMap { requestResult ->
                requestResult.data.let { userDevice ->
                    userPreferences.setDeviceId(userDevice.id)
                    when (requestResult.code) {
                        200 -> {
                            // TODO: Analytics
                        }
                        201 -> {
                            // TODO: Analytics
                        }
                    }
    
                    Single.just(userDevice)
                }
            }
            .onErrorResumeNext { e ->
                val transformedException = transformRequestException(e) { httpException ->
                    return@transformRequestException when (httpException.code()) {
                        409 -> DeviceAlreadyLinkedException()
                        else -> null
                    }
                }
                Single.error(transformedException)
            }
    }
    

    看起来像黑客,但我没有找到更好的解决方案,它的工作。