使用改造对 mvvm 中的 Rxjava 进行错误处理

Posted

技术标签:

【中文标题】使用改造对 mvvm 中的 Rxjava 进行错误处理【英文标题】:Error Handling of Rxjava in mvvm using retrofit 【发布时间】:2020-05-26 11:01:59 【问题描述】:

我正在调用一个提供 Http 状态码 400 的 api

这是我的 NetworkBoundResourceNoDb

public abstract class NetworkBoundResourceNoDb<RequestType> 

    private Observable<Resource<RequestType>> result;

    @MainThread
    protected NetworkBoundResourceNoDb() 
        Observable<Resource<RequestType>> source;
        source = createCall()
            .subscribeOn(Schedulers.io())
            .doOnError(t -> onFetchFailed())
            .observeOn(androidSchedulers.mainThread());

        result = Observable.ambArray(source);
    


    public Observable<Resource<RequestType>> getAsObservable() return result;

    protected boolean onFetchFailed() 
        return false;
    


    @NonNull
    @MainThread
    protected abstract Observable<Resource<RequestType>> createCall();

这是API代码

@GET("api/content/count")
Observable<List<WordCountData>> wordCount();

这是存储库函数

    fun wordCount(): Observable<Resource<List<WordCountData>>>? 
    return object : NetworkBoundResourceNoDb<List<WordCountData>>() 

        override fun createCall(): Observable<Resource<List<WordCountData>>> 
            return courseApi.wordCount()
                .flatMap  learntWords ->
                    Observable.just(
                        if (learntWords == null) Resource.error("", emptyList())
                        else Resource.success(learntWords)
                    )
                
        

    .asObservable

这是视图模型代码

private var wordCount = MutableLiveData<Resource<List<WordCountData>>>()

fun getWordCountLiveData() = wordCount

fun getWordCountList() 
    courseRepository.wordCount()?.subscribe  resource -> getWordCountLiveData().postValue(resource) 

这是我的视图代码

private fun loadWordCount() 
    crViewModel = ViewModelProviders.of(this, viewModelFactory).get(CrViewModel::class.java)
    crViewModel.getWordCountLiveData().observe(this, androidx.lifecycle.Observer 
        resource -> when 
        resource.isLoading -> println("loading")
        resource.data != null -> 
            drawChart(resource.data)
        
        else -> handleErrorResponse()
    
    )
    crViewModel.getWordCountList()

我需要传递 Http 状态码才能查看。我能够在存储库中的 onFetchfailed 中得到错误,同时使用 throwable 参数实现它,但之后无法处理它

它给了我“io.reactivex.exceptions.OnErrorNotImplementedException: HTTP 400”错误

请帮助我提前谢谢

【问题讨论】:

【参考方案1】:

伙计,你在 1 中问了很多问题。

fun getWordCountList() 
courseRepository.wordCount()?.subscribe  resource -> getWordCountLiveData().postValue(resource) 

这是触发所有其他网络代码的代码块。 然而,这个 lambda 只有一个成功参数,而不是一个错误参数。添加第二个 lambda,并用括号括起来,以说明成功和失败:

.subscribe(
    successResponse -> // handle success
, 
 error -> // handle error
)

所以,至少应该处理“OnErrorNotImplementedException”

错误 400 通常意味着您的请求无效,和/或您向请求传递了错误的参数集。对于您提供给我们的大量信息,我无法为您提供帮助,而且对您的服务器一无所知。

最后:“我需要传递 Http 状态码才能查看”。什么??为什么? 你的标题甚至提到了建筑!为什么你的视图层甚至关心来自网络调用的响应代码??

不要那样做。当然,您的视图“可以”知道响应代码,但这是视图层根本不应该知道的。

我希望这会有所帮助。

【讨论】:

谢谢,我是 rx 的新手,我会试试这个......对于那个“http status code in view”,我需要在少数情况下,因为未经授权和用户的其他一些行为需要知道..如果有任何其他方法可以从视图模型本身处理它,这将非常有帮助..再次感谢 好吧..有很多方法,它们在很大程度上取决于你想做什么,你对可能离开用户的圈子了解多少,以及你想向你的用户展示什么样的用户体验用户。软件架构的基础是每一层代码都可以交换,并且不会影响其余的层。在您的示例中,考虑将数据源从网络更改为数据库......现在您不再拥有 200 和 404,因此您的 UI 不应该因此而改变。对于未经授权的情况,请查看 http 拦截器,并使其在 401 上触发

以上是关于使用改造对 mvvm 中的 Rxjava 进行错误处理的主要内容,如果未能解决你的问题,请参考以下文章

Android rxJava 错误处理与改造

使用 Kotlin 进行 RxJava 和改造

带有 rxJava2 和改造的 UndeliverableException

从retrofit2和rxjava中的错误获取url

Rxjava,改造和多次调用

使用 Kotlin 处理错误 RXJava Android