使用改造对 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 进行错误处理的主要内容,如果未能解决你的问题,请参考以下文章