RxJava(二)错误处理

作者: 请你吃鱼 | 来源:发表于2016-08-10 14:05 被阅读1371次

上一篇讲到RxJava的基本用法,但只是正常使用还是不够的,我们在进行网络操作时难免遇到错误的情况,那遇到这些情况时应该怎样处理呢?

 String BASE_URL = "http://123.57.248.61:8089/";

    @GET()
    Call<TokenModel> getToken();

    @GET()
    Call<ChargeModel> getCharge(@Query("token") String token);

    @GET()
    Call<ChargeModel> getCharge();

这里先贴出需要的方法。
现在假设一种情况,我们在查询用户余额时需要先从网络获取一个token来保证安全性(有点牵强),请求token之后需要把token作为参数再从网络请求余额,如果用Retrofit需要这么写:

 ApiManger apiManger = RetrofitHelper.getManger();
        apiManger.getToken().enqueue(new Callback<TokenModel>() {
            @Override
            public void onResponse(Call<TokenModel> call, Response<TokenModel> response) {
                apiManger.getCharge(response.body().getToken()).enqueue(new Callback<ChargeModel>() {
                    @Override
                    public void onResponse(Call<ChargeModel> call, Response<ChargeM
                    }

                    @Override
                    public void onFailure(Call<ChargeModel> call, Throwable t) {

                    }
                });
            }

            @Override
            public void onFailure(Call<TokenModel> call, Throwable t) {

            }
        });

ok,但是请求余额token并不是必要的参数,如果请求token失败后我们还想获取余额,那么就需要这样写:

ApiManger apiManger = RetrofitHelper.getManger();
        apiManger.getToken().enqueue(new Callback<TokenModel>() {
            @Override
            public void onResponse(Call<TokenModel> call, Response<TokenModel> response) {
                apiManger.getCharge(response.body().getToken()).enqueue(new Callback<ChargeModel>() {
                    @Override
                    public void onResponse(Call<ChargeModel> call, Response<ChargeModel> response) {

                    }

                    @Override
                    public void onFailure(Call<ChargeModel> call, Throwable t) {

                    }
                });
            }

            @Override
            public void onFailure(Call<TokenModel> call, Throwable t) {
                apiManger.getCharge().enqueue(new Callback<ChargeModel>() {
                    @Override
                    public void onResponse(Call<ChargeModel> call, Response<ChargeModel> response) {

                    }

                    @Override
                    public void onFailure(Call<ChargeModel> call, Throwable t) {

                    }
                });
            }
        });

谜之缩进毁一生,这尼玛都是什么鬼啊?这里的需求虽然有些奇葩,但在开发过程中难免会遇到,下面我们看一下RxJava怎样优雅的处理这种情况:

ApiManger apiManger = RetrofitHelper.getManger();
        apiManger.getToken()
                .flatMap(new Func1<TokenModel, Observable<ChargeModel>>() {
                    @Override
                    public Observable<ChargeModel> call(TokenModel tokenModel) {
                        return apiManger.getCharge(tokenModel.getToken());
                    }
                })
                .onErrorResumeNext(new Func1<Throwable, Observable<ChargeModel>>() {
                    @Override
                    public Observable<ChargeModel> call(Throwable throwable) {
                        return apiManger.getCharge();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<ChargeNodel>() {
                    @Override
                    public void onCompleted() {
                        
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(ChargeModel chargeModel) {

                    }
                });

先来分析一下这段代码,首先调用getToken获取token之后再调用flatMap方法重新发射流,从这儿之后传递的对象就变成chargeModel了,再往后面遇到了一个onErrorResumeNext操作符,这就是RxJava错误处理的一个操作符,那这个操作符是什么意思呢?onErrorResumeNext操作符接收的是前面传递过来的错误,接收到错误之后就会重新发射一个流,但是如果前面一切正常没有错误发生的话,那这个操作符是不会执行的,这就好比前面的流水线出了故障,就会切换到这条流水线上,但是如果前面的流水线没有问题,这条流水线是不会被启动的。结合我们前面的需求看一下,首先获取token,如果获取成功,则会传递到flatMap中启动获取余额的流,获取余额之后传递到onNext方法中,如果获取token失败,则会传递到onErrorResumeNext中,接着调用无参的getCharge,这样也可以获取余额。
看到这里是不是感觉万事大吉了呢,不要高兴的太早,前面说到onErrorResumeNext会接收前面所有的错误,试想一下这种情况:如果我们在获取token的时候成功了,但是在获取余额的时候失败了,按照Retrofit的做法获取余额失败后就什么操作也没有,既然获取余额都失败了就没必要在做什么了,但是如果按照上面RxJava的写法,不管在哪一步失败他都会执行onErrorResumeNext的,这可不是我们想要的,因为我们无法精准控制哪一步失败需要重新请求,试想如果操作的层次更多的话,难不成每次失败都要进入onErrorResumeNext重新请求一次吗?不过办法总是有的,我们说过flatMap就是重新发射一条流,既然他是一条流,那他完全可以在发射的时候继续添加错误处理,解决办法如下:

 ApiManger apiManger = RetrofitHelper.getManger();
        apiManger.getToken()
                .flatMap(new Func1<TokenModel, Observable<ChargeNodel>>() {
                    @Override
                    public Observable<ChargeModel> call(TokenModel tokenModel) {
                        return apiManger.getCharge(tokenModel.getToken()).onErrorResumeNext(new Func1<Throwable, Observable<? extends ChargeModel>>() {
                            @Override
                            public Observable<? extends ChargeModel> call(Throwable throwable) {
                                return Observable.empty();
                            }
                        });
                    }
                })
                .onErrorResumeNext(new Func1<Throwable, Observable<ChargeModel>>() {
                    @Override
                    public Observable<ChargeModel> call(Throwable throwable) {
                        return apiManger.getCharge();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<ChargeModel>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(ChargeModel chargeModel) {

                    }
                });

我们在flatMap发射流的时候又添加了一个onErrorResumeNext操作符,如果发生错误,那他就会进入后面的onErrorResumeNext,直接返回Observable.empty(),最后调用onCompleted方法。使用retrolambda可以简化成如下代码:

 ApiManger apiManger = RetrofitHelper.getManger();
        apiManger.getToken()
                .flatMap(tokenModel -> apiManger.getCharge(tokenModel.getToken()).onErrorResumeNext(throwable -> Observable.empty()))
                .onErrorResumeNext(throwable1 -> apiManger.getCharge())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(chargeModel -> {
                    
                }, throwable2 -> {

                });

这尼玛也太精简了吧,可以与前面用Retrofit的代码对比一下。好了,本篇文章到此结束,如有错误,欢迎指出!

相关文章

  • RxJava(二)错误处理

    上一篇讲到RxJava的基本用法,但只是正常使用还是不够的,我们在进行网络操作时难免遇到错误的情况,那遇到这些情况...

  • RxJava基础五-错误处理操作符

    此篇内容均是来自书籍《RxJava响应式编程》李衍顺 著 3.5 错误处理操作符 RxJava对错误的处理很方便,...

  • Rxjava错误处理

    在RxJava中错误处理的最佳方式是什么? 原文地址:https://rongi.github.io/kotlin...

  • RxJava 错误处理

    Rx中, 很容易处理异常, 整个链式调用过程中,如果异常不做处理, 最后都会交给onError; 不要过渡的依赖o...

  • RxJava的错误处理一-retry

    RxJava的错误处理主要分为两类,retry系列以及onErrorRetrun系列。retry系列是当错误的时候...

  • RxJava错误处理与线程并发

    错误处理 Rxjava为链式调用,事件从源头流到尽头。一个源头链条中发生异常或者Observable.error(...

  • RxJava全局错误处理

    在RxJava中rx.pluginsRxJavaPlugins这个类是用来处理发生的错误的,在RxJava的源码中...

  • RxJava2

    一、RxJava GitHub: RxJava2Demo 二、RxJava的概念 RxJava RxAndroid...

  • RxJava 操作符(创建、变换)

    概述 RxJava 操作符的类型有多种,如:创建、变换、过滤、组合、错误处理、辅助、条件和布尔操作符等,还有许多延...

  • RxJava 2.x 原理剖析

    一、RxJava 简介: 1.RxJava 定义: 2.RxJava 架构: 二、RxJava 2.x 环境搭建(...

网友评论

    本文标题:RxJava(二)错误处理

    本文链接:https://www.haomeiwen.com/subject/cmadsttx.html