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

从Rx java Android的onError()返回自定义对象,而不是可抛出的对象,android,kotlin,rx-java2,rx-android,Android,Kotlin,Rx Java2,Rx Android,我对RX Java是新手。在通过改型实现RXJava时,我发现我的doError(){} 但是我想要RXJava的doError()返回ErrorBase()->,这是我的自定义类。而不是扔掉 它将帮助我处理中心的错误。我将把我的可抛出对象传递给我处理自定义消息的ErrorBase类 下面是doError()。我要返回ErrorBase对象的位置 apiInterface.getLoginDetails(auth) .doOnNext { //LoginRe

我对RX Java是新手。在通过改型实现RXJava时,我发现我的
doError(){}

但是我想要RXJava的doError()返回ErrorBase()->,这是我的自定义类。而不是扔掉

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

下面是
doError()
。我要返回ErrorBase对象的位置

apiInterface.getLoginDetails(auth)
        .doOnNext {
           //LoginResponse
        }
        doOnError{
        return ErrorBase(throwable)
          }
其他类别的代码

Api接口类

interface ApiInterface {

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

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")
}}
classloginviewmodel@Inject构造函数(
private val loginRepository:loginRepository):ViewModel(){
private val TAG=this.javaClass.name
私有变量loginResult:MutableLiveData=MutableLiveData()
私有变量登录错误:MutableLiveData=MutableLiveData()
私有变量loginLoader:MutableLiveData=MutableLiveData()
私有lateinit var disposableObserver:disposableObserver
fun loginResult():LiveData{
返回登录结果
}
趣味登录错误():LiveData{
返回登录错误
}
fun loginLoader():LiveData{
返回登录器
}
私人娱乐getLoginData(auth:String){
loginLoader.postValue(true)
initLoginObserver()
loginRepository.getLoginDetails(auth)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.去盎司(400毫秒)
.认购(可处置观察员)
}
private fun initLoginObserver(){
disposableObserver=对象:disposableObserver(){
覆盖有趣的onComplete(){
}
覆盖fun onNext(loginDetails:LoginResponseModel){
loginResult.postValue(loginDetails)
loginLoader.postValue(false)
}
覆盖有趣的错误(e:可丢弃){
loginError.postValue(e.message)
loginLoader.postValue(false)
}
}
}
趣味元素{
if(null!=disposableObserver&&!disposableObserver.isDisposed)disposableObserver.dispose()
}
有趣的登录{
getLoginData(“认证”)
}}

首先,
doError
的目的不是转换/返回一些数据,而是帮助处理日志记录等副作用

其次,
ErrorBase
LoginResponseModel
不匹配,因为它们没有任何共同的父对象

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

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

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

    fun getLoginDetails(auth: String): Observable<LoginResponse> {
        return apiInterface.getLoginDetails(auth)
                   .map { data -> LoginResponse.Result(data) }
                   .onErrorReturn { throwable -> LoginResponse.Error(throwable) }
    }
    
  • 一些解释

    • onErrorReturn
      完全满足您的需要-在发生错误时返回您的自定义值

    • 如果不添加
      LoginResponse
      ,则必须使
      可观察
      ,这是一种松散的类型,不能很好地描述您的界面

    • 使
      LoginResponse
      密封只允许检查两种情况下发出的数据是
      结果
      还是
      错误
      。否则,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
        }
    }
    
    密封类响应{
    数据类结果(val结果:T):响应()
    数据类错误(val throwable:throwable):响应()
    }
    有趣的getLoginDetails(auth:String):可观察{
    返回apinterface.getLoginDetails(auth)
    .map{data->Response.Result(数据)}
    .OneErrorReturn{throwable->LoginResponse.Error(throwable)}
    }
    …在你的代码中的某个地方。。
    有趣的手柄应答(应答:应答){
    何时(回应){
    是Response.Result->Response.Result
    是Response.Error->Response.throwable
    }
    }
    
    谢谢您的回答@hluhovskyi。我有一个疑问。如果我必须从不同的屏幕调用另一个api。在这种情况下,我需要相同的错误类,但不同的响应模型。因此,如果我采用这种方法,我需要为每个响应创建单独的错误类?这里有多种方法。您可以为每个调用创建具有不同错误的不同响应。您可以像在它们上面的接口一样进行抽象。您可以创建通用的
    响应
    ,并在任何地方使用它来包装数据。就个人而言,我最喜欢最后一个,所以我会更新答案。但在任何情况下,这取决于您和您的业务需要。很抱歉,我很想知道如何将此响应类与LoginRespone“Model”类1相匹配。每个响应类(LoginResponse)都将继承响应类2。由于我的ErrorBase类不同,如何与Error类链接。我无法消化你不需要继承,你需要包装。每次调用都应返回
    单个
    。在您的情况下,它将是单一的。我所说的
    Response.Error
    是指
    ErrorBase
    但是用另一种方式命名和放置。@hluhovskyi我做了同样的操作,但是没有使用接口.getLoginDetails(auth).map{it->Result(it)}.onerrorrurn{Error(it)}它不工作。在错误(数据)的情况下,它给我错误类型推断失败。预期类型不匹配,并要求我返回块体函数中所需的表达式
    fun getLoginDetails(auth: String): Observable<LoginResponse> {
        return apiInterface.getLoginDetails(auth)
                   .map { data -> LoginResponse.Result(data) }
                   .onErrorReturn { throwable -> LoginResponse.Error(throwable) }
    }
    
    fun doRequest() {
         loginRepository.getLoginDetails(auth)
             .subscribe { result ->
                  when (result) {
                       is LoginResponse.Result -> //do something with result
                       is LoginResponse.Error -> //do something with error
                  }
             }
    }
    
    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
        }
    }