android - 从 Rx java Android 的 onError() 返回自定义对象而不是可抛出对象

标签 android kotlin rx-java2 rx-android

我是 RX Java 新手。在使用 Retrofit 实现 Rx java 时,我发现我的 doOnError(){}

中得到了可抛出对象

但是我想要 RX Java 的 doOnError() 应该返回 ErrorBase() -> 这是我的自定义类。而不是可扔的。

它将帮助我处理中央的错误。我将把可抛出对象传递给我处理自定义消息的 ErrorBase 类。

下面是doOnError()。我想在哪里返回 ErrorBase 对象

apiInterface.getLoginDetails(auth)
        .doOnNext {
           //LoginResponse
        }
        doOnError{
        return ErrorBase(throwable)
          }

其他类的代码。

Api接口(interface)类

interface ApiInterface {

@POST("login")
fun getLoginDetails(@Header(Constants.AUTHORIZATION) auth: String): Observable<LoginResponseModel>
} 

登录存储库

class LoginRepository @Inject constructor(private val apiInterface: ApiInterface,
                                      val utils: Utils) {


fun getLoginDetails(auth: String): Observable<LoginResponseModel> {

    return apiInterface.getLoginDetails(auth)
            .doOnNext {
            }
            .doOnError {
              //Right now having throw-able object
            }

}
}

错误库

class ErrorBase(private val throwable: Throwable) {

private var message: String?
private var statusCode: Int


init {
    statusCode = getStatusCode()
    message = getMessage()
}

private fun getStatusCode(): Int {
    if (throwable is HttpException) {
        val exception = throwable
        return exception.code()
    }
    return -1
}

private fun getMessage() =
        when (throwable) {
            is IOException -> "Something Went Wrong"
            is UnknownHostException -> "No internet connectivity"
            is SocketTimeoutException -> "Slow Internet connectivity"
            else -> throwable.message
        }
}

LoginvViewModel

class LoginViewModel @Inject constructor(
    private val loginRepository: LoginRepository) : ViewModel() {
private val TAG = this.javaClass.name
private var loginResult: MutableLiveData<LoginResponseModel> = MutableLiveData()
private var loginError: MutableLiveData<String> = MutableLiveData()
private var loginLoader: MutableLiveData<Boolean> = MutableLiveData()

private lateinit var disposableObserver: DisposableObserver<LoginResponseModel>

fun loginResult(): LiveData<LoginResponseModel> {
    return loginResult
}

fun loginError(): LiveData<String> {
    return loginError
}

fun loginLoader(): LiveData<Boolean> {
    return loginLoader
}


private fun getLoginData(auth: String) {
    loginLoader.postValue(true)
    initLoginObserver()
    loginRepository.getLoginDetails(auth)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .debounce(400, MILLISECONDS)
            .subscribe(disposableObserver)
}

private fun initLoginObserver() {
    disposableObserver = object : DisposableObserver<LoginResponseModel>() {
        override fun onComplete() {

        }

        override fun onNext(loginDetails: LoginResponseModel) {
            loginResult.postValue(loginDetails)
            loginLoader.postValue(false)
        }

        override fun onError(e: Throwable) {
            loginError.postValue(e.message)
            loginLoader.postValue(false)
        }
    }
}

fun disposeElements() {
    if (null != disposableObserver && !disposableObserver.isDisposed) disposableObserver.dispose()
}

fun loginClicked() {
    getLoginData("auth")
}}

最佳答案

首先,doOnError并非旨在转换/返回某些数据,而是有助于处理日志记录等副作用。

第二件事,ErrorBaseLoginResponseModel 不太适合因为他们没有共同的 parent 。

因此,我建议您采用以下解决方案:

  1. 为您的响应创建一个基类:

    sealed class LoginResponse {
    
        class Result( ..your data here.. ) : LoginResponse()
    
        class Error( ... ) : LoginResponse()
    }
    
  2. 使函数返回 LoginResponse并进行以下更改:

    fun getLoginDetails(auth: String): Observable<LoginResponse> {
        return apiInterface.getLoginDetails(auth)
                   .map { data -> LoginResponse.Result(data) }
                   .onErrorReturn { throwable -> LoginResponse.Error(throwable) }
    }
    
  3. 现在两个结果都有一个共同的父结果,您可以使用 getLoginDetails通过以下方式:

    fun doRequest() {
         loginRepository.getLoginDetails(auth)
             .subscribe { result ->
                  when (result) {
                       is LoginResponse.Result -> //do something with result
                       is LoginResponse.Error -> //do something with error
                  }
             }
    }
    

一些解释。

  • onErrorReturn完全按照您的需要 - 返回您的自定义值,以防发生错误

  • 如果不添加LoginResponse你必须做 Observable<Any>这是松散类型的,并不能很好地描述您的界面。

  • 制作LoginResponse sealed 只允许检查 2 种情况:发出的数据是否为 ​​ResultError 。否则,Kotlin 编译器会强制您添加额外的 else分支

更新如果您需要在多个地方做同样的事情,您可以这样做:

sealed class Response<T> {

    data class Result<T>(val result: T) : Response<T>()

    data class Error<T>(val throwable: Throwable) : Response<T>()
}

fun getLoginDetails(auth: String): Observable<Response<LoginResponseModel>> {
    return apiInterface.getLoginDetails(auth)
               .map<Response<LoginResponseModel>> { data -> Response.Result(data) }
               .onErrorReturn { throwable -> LoginResponse.Error(throwable) }
}

..and somewhere in your code..

fun handleResponse(response: Response<LoginData>) {
    when (response) {
        is Response.Result -> response.result
        is Response.Error -> response.throwable
    }
}

关于android - 从 Rx java Android 的 onError() 返回自定义对象而不是可抛出对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50599152/

相关文章:

android - 再次开始 Retrofit 调用,从 RXJava 中的 onError 回调再次订阅 Observable

android - 与 ObservableField<> 的 2 向数据绑定(bind),set() 不起作用?

java - Android:在JDK 10上为1.8目标构建Java代码时出现Gradle错误(gradle build-> NullPointerException)

kotlin - 开放类和抽象类有什么区别?

java - 在 Kotlin 中启用 CORS 时,Spark 在访问路线时返回空响应

java - 如何在 Observable RxJava 中处理处置

android - 在Android中显示任意大小的位图

android - 可变状态是否在 compose 中堆叠

android - Kotlin 中 Dagger 2 的未解决引用

android - 无法使用 TestSubscriber 订阅 RxJava 2 Observable