从Rx java Android的onError()返回自定义对象,而不是可抛出的对象
我对RX Java是新手。在通过改型实现RXJava时,我发现我的从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
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
}
}