RetroHttp(四) — 实现串联请求

前言

RetroHttp作为一个基于Retrofit2.x网络请求的封装库,致力于简洁快速的实现网络通讯,在之前的文章里,我已经对RetroHttp的使用做了些相关介绍,大家感兴趣的话可以参考以下文章:
RetroHttp(一) — 下载使用介绍
RetroHttp(二) — 下载支持增量更新
RetroHttp(三) — kotlin版网络请求

Android网络请求过程中,我们有时会遇到请求串联的情况。即第一个请求发起成功后,才能发起第二个请求。那么今天就让我们来了解下RetroHttp基于串联请求的使用吧。

今天涉及知识有:

  1. 串联请求业务逻辑
  2. 串联请求帮助类ObservableHelper方法简介
  3. 串联请求的使用示例
  4. 需要注意的事项

一. 串联请求业务逻辑

在开发过程中,有时我们回遇到串联请求的情况,如发起注册通讯成功后,立马发起登录的通讯。他们的逻辑特点是,第一个通讯成功后,才发起第二个通讯,当第一个通讯发送失败后,则终止发起后续通讯。这里我将此种通讯逻辑称为串联请求

二.串联请求帮助类ObservableHelper方法简介

RetroHttp库中也支持串联请求,其功能封装到帮助类ObservableHelper中。下面就来看看
ObservableHelper中关于串联请求的方法吧:

    /***
     * 接连发起多个通讯的Observable(一个接一个,但顺序不确定)
     *
     * @param observable
     * @param function  Function<T,R>: T->进入该方法的参数, R->输出结果
     * @param <T>
     * @return
     */
    public static <T>Observable getNextObservable(Observable<T>observable, Function<T, ObservableSource<T>> function)

    /***
     * 按顺序发起通讯的Observable(一个接一个,且按顺序发送)
     *
     * @param observable
     * @param function Function<T,R>: T->进入该方法的参数, R->输出结果
     * @param <T>
     * @return
     */
    public static <T> Observable getNextObservableInOrder(Observable<T>observable, Function<T, ObservableSource<T>> function)

ObservableHelper类支持发起无序有序串联请求,主要如下:

  • getNextObservable: 支持发起无序串联请求
  • getNextObservableInOrder: 支持发起有序串联请求

无序串联请求即依次发起ABC三个网络请求,但三个请求返回结果的顺序未知。有序串联请求即依次发起ABC三个网络请求,返回结果的顺序也为ABC

三.串联请求的使用示例

下面以有序串联请求为例,给出其在Presenter中发起网络请求的核心代码:

3.1 Java 版
    public void checkVersion() {
        ApiService apiService = (ApiService) ApiRetrofitor.getInstance().getBaseRetrofitor().getApiService();
        //发起第一个请求
        Observable observable = apiService.checkVersion();
        observable = ObservableHelper.getNextObservableInOrder(observable, new Function<ResponseData, ObservableSource<ResponseData>>() {
            @Override
            public ObservableSource<ResponseData> apply(ResponseData responseData) throws Exception{
                LogUtil.i("=======Function执行apply======");

                //解析第一个通讯的结果
                int code = responseData.getCode();
                //只有在第一此通讯顺利的时候,才发起第二次通讯
                if (code == ResponseCode.SUCCES_CODE) {//成功
                    LogUtil.i("=======准备发起第二次通讯======");
                    //准备发起第二次通讯
                    RequestUser user = new RequestUser();
                    user.setUsername("xxxx");
                    user.setPassword("xxxxxx");
                    return apiService.login(user);
                }
                return null;
            }
        });

//        //按顺序发起第三个通讯
//        observable = ObservableHelper.getNextObservableInOrder(observable, new Function<> ...)

        //加载loading
        LoadingDialog.getInstance().showLoading(mContext);
        //处理最后一次通讯的结果
        RxManager.connect(observable, new ApiObserver<ResponseData>() {
            @Override
            public void doNext(ResponseData responseData) {
                LoadingDialog.getInstance().hideLoading();

                int code = responseData.getCode();
                String message = responseData.getMessage();
                if (code == ResponseCode.SUCCES_CODE) {//成功

                    Object object=responseData.getData();
                    if(object!=null){
                        String temp= GsonUtil.gsonString(object);
                        User user= GsonUtil.gsonToBean(temp,User.class);
                        mView.loginSuccess(user);
                    }else{
                        mView.loginFail("获取信息为空");
                    }
                } else {
                    mView.loginFail(message);
                }
            }

            @Override
            public void doError(ServerException e) {
                LoadingDialog.getInstance().hideLoading();

                LogUtil.i("=====error====="+e.getMessage());
                mView.loginFail("发生错误");

            }
        });
    }
3.2 Kotlin版
    fun checkVersion() {
        var apiService =ApiRetrofitor.getBaseRetrofitor<BaseRetrofitor>().apiService as ApiService
        //发起第一个请求
        var observable: Observable<ResponseData<Any>> = apiService.checkVersion()
        observable = ObservableHelper.getNextObservableInOrder(
            observable,object : Function<ResponseData, ObservableSource<ResponseData>>() {
                @Throws(Exception::class)
                fun apply(responseData: ResponseData): ObservableSource<ResponseData>? {
                    LogUtil.i("=======Function执行apply======")

                    //解析第一个通讯的结果
                    var code = responseData.code
                    //只有在第一此通讯顺利的时候,才发起第二次通讯
                    if (code == ResponseCode.SUCCES_CODE) {//成功
                        LogUtil.i("=======准备发起第二次通讯======")
                        //准备发起第二次通讯
                        var user = RequestUser()
                        user.setUsername("xxxx")
                        user.setPassword("xxxxxx")
                        return apiService.login(user)
                    }
                    return null
                }
            })

//        //按顺序发起第三个通讯
//        observable = ObservableHelper.getNextObservableInOrder(observable, new Function<> ...)

        //加载loading
        LoadingDialog.getInstance().showLoading(mContext)
        //处理最后一次通讯的结果
        RxManager.connect(observable, object : ApiObserver<ResponseData>() {
            fun doNext(responseData: ResponseData) {
                LoadingDialog.getInstance().hideLoading()

                var code = responseData.code
                var message = responseData.message
                if (code == ResponseCode.SUCCES_CODE) {//成功

                    var obj = responseData.data
                    if (obj != null) {
                        var temp = GsonUtil.gsonString(obj)
                        var user = GsonUtil.gsonToBean(temp, User::class.java)
                        mView.loginSuccess(user)
                    } else {
                        mView.loginFail("获取信息为空")
                    }
                } else {
                    mView.loginFail(message)
                }
            }

            fun doError(e: ServerException) {
                LoadingDialog.getInstance().hideLoading()

                LogUtil.i("=====error=====" + e.message)
                mView.loginFail("发生错误")
            }
        })
    }

四.需要注意的事项

这里需要注意的是,以上面依次发起的两个请求为例,checkVersion()发起的请求在第一个getNextObservableInOrder中接收并处理,然后在该方法的apply(T t)方法中一般只处理第一个同通讯获取成功的情况,处理OK后接着在此方法中发起第二个请求。若第一个通讯失败,则失败的处理会有结尾的RxManager.connect(...)来处理。若还想发起第三个请求,则像上面代码一样,在后面接着写observable = ObservableHelper.getNextObservableInOrder(observable, new Function<> ...),然后在此方法中处理第二个请求的接收值,处理完后,发起第三个请求...
最后用RxManager.connect(...)来处理最后一个请求的返回值。值得注意的是,在RxManager.connect(...)doError(ServerException e)中将处理所有请求的异常处理。由于串联请求的特点,会导致doError(ServerException e)无法判断处理的是哪一个通讯的异常,故在开发过程中,我们只会在doError(ServerException e)中提供针对最后一次通讯的模糊提示。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容