国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

網(wǎng)絡(luò)庫與Rxjava2結(jié)合常見使用場(chǎng)景介紹

BDEEFE / 2434人閱讀

摘要:本文主要是講與怎么結(jié)合的,也不會(huì)的操作符深入講解,不然就脫離了本文的重心廢話不多說了,一起來看看是如何使用的。延遲請(qǐng)求利用的操作符。

前言

之前在github開源過一個(gè)網(wǎng)絡(luò)庫RxEasyHttp,這是一款基于RxJava2+Retrofit2實(shí)現(xiàn)簡單易用的網(wǎng)絡(luò)請(qǐng)求框架。在這里對(duì)網(wǎng)絡(luò)庫的用法就不做過多介紹,感興趣的可以去了解下。在使用過程中一些網(wǎng)友反饋不知道怎么結(jié)合Rxjava2來實(shí)現(xiàn)一些場(chǎng)景需求,希望能夠?qū)懸槐槲恼陆榻B下。終于抽出時(shí)間來對(duì)與Rxjava2在實(shí)際場(chǎng)景使用的一些案例做個(gè)簡單的總結(jié)和介紹。不知道怎么使用,主要是對(duì)RxEasyHttp有個(gè)誤區(qū),RxEasyHttp不僅是支持采用鏈?zhǔn)秸{(diào)用一點(diǎn)到底方便使用,同時(shí)也支持返回Observable的用法,拿到了Observable自然就可以很好的利用Rxjava操作符了來實(shí)現(xiàn)各種強(qiáng)大的功能。本文主要是講RxEasyHttp與Rxjava2怎么結(jié)合的,也不會(huì)Rxjava2的操作符深入講解,不然就脫離了本文的重心!廢話不多說了,一起來看看是如何使用的。

場(chǎng)景介紹 場(chǎng)景一:延遲請(qǐng)求

在頁面網(wǎng)絡(luò)接口請(qǐng)求中,不是希望立馬請(qǐng)求,而是需要延遲指定的時(shí)間后再去請(qǐng)求。
延遲請(qǐng)求:利用RxJava的timer操作符。
timer:主要作用就是創(chuàng)建一個(gè)Observable,它在一個(gè)給定的延遲后發(fā)射一個(gè)特殊的值,只是延遲發(fā)送一次并不會(huì)按照周期執(zhí)行。
timer()源碼如下:

 public static Observable timer(long delay, TimeUnit unit) {
        return timer(delay, unit, Schedulers.computation());
    }

可以看到采用timer()返回的是Observable,而網(wǎng)絡(luò)請(qǐng)求返回的Observable并不是Observable,如何將這兩個(gè)Observable關(guān)聯(lián)起來,就需要采用另外一個(gè)操作符flatMap(),簡單理解就是flatMap使用一個(gè)指定的函數(shù)對(duì)原始Observable發(fā)射的每一項(xiàng)數(shù)據(jù)進(jìn)行相應(yīng)的變換操作。flatMap詳細(xì)作用不做過多介紹。
例如:延遲5秒請(qǐng)求

        //延遲5s請(qǐng)求
        Observable.timer(5, TimeUnit.SECONDS).flatMap(new Function>() {
            @Override
            public ObservableSource apply(@NonNull Long aLong) throws Exception {
                //延遲結(jié)束開始執(zhí)行網(wǎng)絡(luò)請(qǐng)求
                Observable observable = EasyHttp.get("/v1/app/chairdressing/skinAnalyzePower/skinTestResult")
                        .timeStamp(true)
                        .execute(SkinTestResult.class);
                return observable;
            }
        }).subscribe(new BaseSubscriber() {
            @Override
            protected void onStart() {
            }

            @Override
            public void onError(ApiException e) {
                showToast(e.getMessage());
            }

            @Override
            public void onNext(@NonNull SkinTestResult skinTestResult) {
                Log.i("test", "=====" + skinTestResult.toString());
            }
        });
        
        //在不需要輪詢的時(shí)候,取消輪詢
        //EasyHttp.cancelSubscription(polldisposable);

timer在這里作用延遲5s結(jié)束時(shí)就會(huì)觸發(fā)網(wǎng)絡(luò)請(qǐng)求

flatMap在這里的作用就是將timer操作符返回的Observable和網(wǎng)絡(luò)請(qǐng)求的Observable做轉(zhuǎn)換,在subscribe訂閱時(shí)返回的內(nèi)容,我們真正需要的SkinTestResult,而不是Long. 因此將Observable變換成Observable輸出SkinTestResult,完美達(dá)到目的。

場(chǎng)景二:輪詢請(qǐng)求-無限輪詢

在項(xiàng)目中需要用到每隔5s刷新一次頁面或者拉取最新消息。輪詢器大家一定不陌生,開發(fā)中無論是Java的Timer+TimeTask , 還是Android的Hanlder都可實(shí)現(xiàn),現(xiàn)在介紹另一種簡單的實(shí)現(xiàn)方式。
無限輪詢:利用RxJava的Interval操作符。
interval:創(chuàng)建一個(gè)按固定時(shí)間間隔發(fā)射整數(shù)序列的Observable,它是按照周期執(zhí)行的。源碼如下(只展示相關(guān)的兩個(gè)方法):

 public static Observable interval(long initialDelay, long period, TimeUnit unit) {
        return interval(initialDelay, period, unit, Schedulers.computation());
    }
    
    public static Observable interval(long period, TimeUnit unit) {
        return interval(period, period, unit, Schedulers.computation());
    }

可以看到采用interval()返回的是Observable,而網(wǎng)絡(luò)請(qǐng)求返回的Observable并不是Observable,如何將這兩個(gè)Observable關(guān)聯(lián)起來,就需要采用另外一個(gè)操作符flatMap(),簡單理解就是flatMap使用一個(gè)指定的函數(shù)對(duì)原始Observable發(fā)射的每一項(xiàng)數(shù)據(jù)之行相應(yīng)的變換操作。flatMap詳細(xì)作用不做過多介紹(同上場(chǎng)景一)。
例如:間隔5s輪詢一次

        //自己根據(jù)需要選擇合適的interval方法
        Disposable polldisposable = Observable.interval(0, 5, TimeUnit.SECONDS).flatMap(new Function>() {
            @Override
            public ObservableSource apply(@NonNull Long aLong) throws Exception {
                return EasyHttp.get("/ajax.php")
                        .baseUrl("http://fy.iciba.com")
                        .params("a", "fy")
                        .params("f", "auto")
                        .params("t", "auto")
                        .params("w", "hello world")
                        //采用代理
                        .execute(new CallClazzProxy, Content>(Content.class) {
                        });
            }
        }).subscribeWith(new BaseSubscriber() {
            @Override
            public void onError(ApiException e) {
                showToast(e.getMessage());
            }

            @Override
            public void onNext(@NonNull Content content) {
                showToast(content.toString());
            }
        });
        
        //在不需要輪詢的時(shí)候,取消輪詢
        //EasyHttp.cancelSubscription(polldisposable);

interval在這里作用每隔5s結(jié)束時(shí)就會(huì)觸發(fā)網(wǎng)絡(luò)請(qǐng)求

注意interval(0, 5, TimeUnit.SECONDS)interval(5, TimeUnit.SECONDS)的區(qū)別,自己根據(jù)需要選擇合適的interval方法。

interval(0,5, TimeUnit.SECONDS):3個(gè)參數(shù),第一個(gè)參數(shù)表示初始化延時(shí)多久開始請(qǐng)求,這里用0表示不延時(shí)直接請(qǐng)求,第二個(gè)參數(shù)表示間隔多久輪詢一次,這里表示間隔5s,第三個(gè)表示設(shè)置的時(shí)間單位。interval(5, TimeUnit.SECONDS):2個(gè)參數(shù),其中的這個(gè)5就表示,初始延時(shí)5秒開始執(zhí)行請(qǐng)求,輪詢也是5s,第二個(gè)表示設(shè)置的時(shí)間單位,從上面提供的interval()源碼可以看出。

flatMap在這里的作用就是將intervalObservable和網(wǎng)絡(luò)請(qǐng)求的Observable做轉(zhuǎn)換,輸出Content,而不是Long.

場(chǎng)景三:輪詢請(qǐng)求-限定次數(shù)輪詢

這個(gè)和無限輪詢用法基本一樣,只是多了輪詢的次數(shù)限制條件,不是一直無限的輪詢下去。
輪詢次數(shù):利用RxJava的intervalRange或者take操作符。
intervalRange:以一個(gè)例子說明可能更清楚,intervalRange(0,3,0,5, TimeUnit.SECONDS)表示從0開始輸出3個(gè)數(shù)據(jù),延遲0秒執(zhí)行,每隔5秒執(zhí)行一次。
take:表示只取前n項(xiàng)。這里用take和interval操作符聯(lián)合使用,由于一旦interval計(jì)時(shí)開始除了解綁就無法停止,使用take操作符就簡單很多了,它的意思是只釋放前n項(xiàng),過后Observable流就自動(dòng)終止。
例如:只輪詢3次

        int count = 3;//輪詢3次
        //方式一:采用intervalRange
        //Observable.intervalRange(0,count,0,5, TimeUnit.SECONDS).flatMap(new Function>() {
        //方式一:采用take
        countdisposable = Observable.interval(0, 5, TimeUnit.SECONDS).take(count).flatMap(new Function>() {
            @Override
            public ObservableSource apply(@NonNull Long aLong) throws Exception {
                return EasyHttp.get("/ajax.php")
                        .baseUrl("http://fy.iciba.com")
                        .params("a", "fy")
                        .params("f", "auto")
                        .params("t", "auto")
                        .params("w", "hello world")
                        //采用代理
                        .execute(new CallClazzProxy, Content>(Content.class) {
                        });
            }
        }).subscribeWith(new BaseSubscriber() {

            @Override
            public void onError(ApiException e) {
                showToast(e.getMessage());
            }

            @Override
            public void onNext(@NonNull Content content) {
                showToast(content.toString());
            }
        });
        
         //在不需要輪詢的時(shí)候,取消輪詢
        //EasyHttp.cancelSubscription(polldisposable);
場(chǎng)景四:輪詢請(qǐng)求-條件輪詢

條件輪詢和限定次數(shù)輪詢比較像,都是起達(dá)到目的后終止輪詢。比如一個(gè)網(wǎng)絡(luò)請(qǐng)求一直在輪詢執(zhí)行,直到獲取到了想要的內(nèi)容后就終止掉輪詢。
條件輪詢:利用RxJava的takeUntil操作符。
takeUntil:使用一個(gè)標(biāo)志Observable是否發(fā)射數(shù)據(jù)來判斷,當(dāng)標(biāo)志Observable沒有發(fā)射數(shù)據(jù)時(shí),正常發(fā)射數(shù)據(jù),而一旦標(biāo)志Observable發(fā)射過了數(shù)據(jù)則后面的數(shù)據(jù)都會(huì)被丟棄。
例如:輪詢請(qǐng)求中如果返回的內(nèi)容字符串中包含“示”就終止輪詢

Observable.interval(0, 5, TimeUnit.SECONDS).flatMap(new Function>() {
            @Override
            public ObservableSource apply(@NonNull Long aLong) throws Exception {
                return EasyHttp.get("/ajax.php")
                        .baseUrl("http://fy.iciba.com")
                        .params("a", "fy")
                        .params("f", "auto")
                        .params("t", "auto")
                        .params("w", "hello world")
                        //采用代理
                        .execute(new CallClazzProxy, Content>(Content.class) {
                        });
            }
        }).takeUntil(new Predicate() {
            @Override
            public boolean test(@NonNull Content content) throws Exception {
                //如果條件滿足,就會(huì)終止輪詢,這里邏輯可以自己寫
                //結(jié)果為true,說明滿足條件了,就不在輪詢了
                return content.getOut().contains("示");
            }
        }).subscribeWith(new BaseSubscriber() {
            @Override
            public void onError(ApiException e) {
                showToast(e.getMessage());
            }

            @Override
            public void onNext(@NonNull Content content) {
                showToast(content.toString());
            }
        });
        
          //在不需要輪詢的時(shí)候,取消輪詢
        //EasyHttp.cancelSubscription(polldisposable);
場(chǎng)景五:輪詢請(qǐng)求-過濾輪詢

過濾輪詢主要是指在輪詢的過程中對(duì)訂閱的內(nèi)容做過濾,不是需要的內(nèi)容就不會(huì)返回給訂閱者,但是它不會(huì)中斷輪詢。過濾輪詢也可以理解成是無限輪詢加了一個(gè)過濾條件而已。
過濾輪詢:利用Rxjava的filter操作符。
filter:是對(duì)源Observable產(chǎn)生的結(jié)果按照指定條件進(jìn)行過濾,只有滿足條件的結(jié)果才會(huì)提交給訂閱者。
例如:返回的狀態(tài)碼如果是錯(cuò)誤就不返回給訂閱者,不更新界面(只有保證每次請(qǐng)求成功才刷新界面),但是會(huì)繼續(xù)輪詢請(qǐng)求

        Disposable filterdisposable = Observable.interval(0, 5, TimeUnit.SECONDS).flatMap(new Function>() {
            @Override
            public ObservableSource apply(@NonNull Long aLong) throws Exception {
                return EasyHttp.get("/ajax.php")
                        .baseUrl("http://fy.iciba.com")
                        .params("a", "fy")
                        .params("f", "auto")
                        .params("t", "auto")
                        .params("w", "hello world")
                        //采用代理
                        .execute(new CallClazzProxy, Content>(Content.class) {
                        });
            }
        }).filter(new Predicate() {
            @Override
            public boolean test(@NonNull Content content) throws Exception {
                //如果不滿足條件就過濾該條輪詢數(shù)據(jù),但是輪詢還是一直執(zhí)行
                //ErrNo==0表示成功,如果不等于0就認(rèn)為失敗,content不會(huì)返回給訂閱者
                return content.getErrNo() != 0;
            }
        }).subscribeWith(new BaseSubscriber() {
            @Override
            public void onError(ApiException e) {
                showToast(e.getMessage());
            }

            @Override
            public void onNext(@NonNull Content content) {
                showToast(content.toString());
            }
        });

         //在不需要輪詢的時(shí)候,取消輪詢
        //EasyHttp.cancelSubscription(polldisposable);

filter操作符在這里只是為了舉列說明,是自己為了講解定義了一個(gè)過濾輪詢的概念,不是說filter只能在輪詢這里使用,它是可以和其它任何Rxjava操作符配合使用。

切記takeUntilfilter的區(qū)別,takeUntil找到自己想要的數(shù)據(jù)后就結(jié)束了流,不再執(zhí)行任何操作。filter發(fā)現(xiàn)不符合條件的不會(huì)給訂閱者,只有符合條件的才給訂閱者,發(fā)現(xiàn)不符合的,不會(huì)中斷操作。

場(chǎng)景六:嵌套請(qǐng)求

在開發(fā)中由于請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)頻繁,往往后面一個(gè)請(qǐng)求的參數(shù)是前面一個(gè)請(qǐng)求的結(jié)果,于是經(jīng)常需要在前面一個(gè)請(qǐng)求的響應(yīng)中去發(fā)送第二個(gè)請(qǐng)求,從而造成“請(qǐng)求嵌套”的問題。如果層次比較多,代碼可讀性和效率都是問題。嵌套請(qǐng)求:利用RxJava的flatMap操作符。
flatMap:是一個(gè)Observable的操作符,接受一個(gè)Func1閉包,這個(gè)閉包的第一個(gè)函數(shù)是待操作的上一個(gè)數(shù)據(jù)流中的數(shù)據(jù)類型,第二個(gè)是這個(gè)flatMap操作完成后返回的數(shù)據(jù)類型的被封裝的Observable。說白了就是將一個(gè)多級(jí)數(shù)列“拍扁”成了一個(gè)一級(jí)數(shù)列。
例如:網(wǎng)絡(luò)請(qǐng)求獲取到token后,把token當(dāng)成另一個(gè)接口的參數(shù),一個(gè)接口依賴另一個(gè)接口。

//第一個(gè)網(wǎng)絡(luò)請(qǐng)求獲取到token
Observable login = EasyHttp.post(ComParamContact.Login.PATH)
                .params(ComParamContact.Login.ACCOUNT, "186****4275")
                .params(ComParamContact.Login.PASSWORD, MD5.encrypt4login("123456", AppConstant.APP_SECRET))
                .sign(true)
                .timeStamp(true).execute(AuthModel.class);
        login.flatMap(new Function>() {
            @Override
            public ObservableSource apply(@NonNull AuthModel authModel) throws Exception {
             //獲取到的token,給到第二個(gè)網(wǎng)絡(luò)當(dāng)參數(shù)。第二個(gè)網(wǎng)絡(luò)開始請(qǐng)求
                return EasyHttp.get("/v1/app/chairdressing/skinAnalyzePower/skinTestResult")
                        .params("accessToken", authModel.getAccessToken())//這個(gè)地方只是舉例,并不一定是需要accessToken
                        .timeStamp(true)
                        .execute(SkinTestResult.class);
            }
        }).subscribe(new ProgressSubscriber(this, mProgressDialog) {
            @Override
            public void onError(ApiException e) {
                super.onError(e);
                showToast(e.getMessage());
            }

            @Override
            public void onNext(SkinTestResult skinTestResult) {
                showToast(skinTestResult.toString());
            }
        });
本例中只是展示了2個(gè)接口的嵌套請(qǐng)求,flatMap其實(shí)是可以支持嵌套很多個(gè)接口請(qǐng)求
場(chǎng)景七:合并請(qǐng)求(zip)

zip合并請(qǐng)求就是指當(dāng)一個(gè)頁面有多個(gè)不同的數(shù)據(jù)來源,既就是有多個(gè)不同的網(wǎng)絡(luò)請(qǐng)求接口,等待這些所有的接口都請(qǐng)求完成后才返回給訂閱者,刷新界面等操作。
zip:使用一個(gè)函數(shù)組合多個(gè)Observable發(fā)射的數(shù)據(jù)集合,然后再發(fā)射這個(gè)結(jié)果.
例如:一個(gè)頁面有3個(gè)不同數(shù)據(jù)來源的網(wǎng)絡(luò)請(qǐng)求接口,等待全部請(qǐng)求完成后才返回

        Observable mobileObservable = EasyHttp.get("http://apis.juhe.cn/mobile/get")
                .params("phone", "18688994275")
                .params("dtype", "json")
                .params("key", "5682c1f44a7f486e40f9720d6c97ffe4")
                .execute(new CallClazzProxy, ResultBean>(ResultBean.class) {
                });

        Observable searchObservable = EasyHttp.get("/ajax.php")
                .baseUrl("http://fy.iciba.com")
                .params("a", "fy")
                .params("f", "auto")
                .params("t", "auto")
                .params("w", "hello world")
                //采用代理
                .execute(new CallClazzProxy, Content>(Content.class) {
                });

        Observable> listObservable = EasyHttp.get("http://news-at.zhihu.com/api/3/sections")
                .execute(new CallClazzProxy>, List>(new TypeToken>() {
                }.getType()) {
                });
        //new Function3最后一個(gè)參數(shù)這里用的是List,表示將3個(gè)返回的結(jié)果,放在同一個(gè)集合最終一次性返回,
         你也可以指定返回其它你需要的數(shù)據(jù)類型     并不一定是List
        //假如這三個(gè)接口返回的都是TestBean,那么就可以直接用具體的List,不需要用List
        Observable.zip(mobileObservable, searchObservable, listObservable, new Function3, List>() {
            @Override
            public List apply(@NonNull ResultBean resultbean, @NonNull Content content, @NonNull List sectionItems) throws Exception {
                //將接收到的3個(gè)數(shù)據(jù)先暫存起來,一次性發(fā)給訂閱者
                List list = new ArrayList();
                list.add(resultbean);
                list.add(content);
                list.add(sectionItems);
                //這里也可以進(jìn)行邏輯處理,處理成你自己需要的結(jié)果后,再返回。
                return list;
            }
        }).subscribe(new BaseSubscriber>() {
            @Override
            public void onError(ApiException e) {
                showToast(e.getMessage());
            }

            @Override
            public void onNext(@NonNull List objects) {
                showToast(objects.toString());
            }
        });

1.zip的參數(shù)中前幾個(gè)參數(shù)都表示數(shù)據(jù)源ObservableSource,最后一個(gè)參數(shù)new Function會(huì)輸出結(jié)果,前面如果有2個(gè)數(shù)據(jù)源就用Function2,3個(gè)數(shù)據(jù)源就用Function3.
2.Function的作用主要是會(huì)返回所有參與zip的結(jié)果內(nèi)容,例如本例是有3個(gè)數(shù)據(jù)源(3個(gè)網(wǎng)絡(luò)接口請(qǐng)求對(duì)應(yīng)的Observable),返回的內(nèi)容是new Function3, List> 其中ResultBean, Content, List是三個(gè)網(wǎng)絡(luò)接口各自返回的內(nèi)容。但是最后一個(gè)參數(shù)List表示什么呢?這一個(gè)就表示最終要給訂閱著subscribe的內(nèi)容,例如本例new BaseSubscriber>()。這里我是將返回的結(jié)果用一個(gè)List集合存起來,然后返回給訂閱者。最終想返回什么是根據(jù)自己的業(yè)務(wù)邏輯需求而定,并不一定就是List,切記!切記!切記! 場(chǎng)景八:合并請(qǐng)求(merge)

剛才講解了zip合并請(qǐng)求,這是合并請(qǐng)求的另一種場(chǎng)景實(shí)現(xiàn)方式merge,一定要注意merge和zip的區(qū)別,雖然都是合并多個(gè)請(qǐng)求,但是是有區(qū)別的,請(qǐng)注意使用場(chǎng)景. 本例中利用Rxjava的merge、mergeDelayError操作符。
merge:將多個(gè)Observalbe發(fā)射的數(shù)據(jù)項(xiàng),合并到一個(gè)Observable中再發(fā)射出去,可能會(huì)讓合并的Observable發(fā)射的數(shù)據(jù)交錯(cuò)(concat操作符是連接不會(huì)出現(xiàn)交錯(cuò)),如果在合并的途中出現(xiàn)錯(cuò)誤,就會(huì)立即將錯(cuò)誤提交給訂閱者,將終止合并后的Observable。
mergeDelayErrormergeDelayError操作符類似于merge操作符,唯一不同就是如果在合并途中出現(xiàn)錯(cuò)誤,不會(huì)立即發(fā)射錯(cuò)誤通知,而是保留錯(cuò)誤直到合并后的Observable將所有的數(shù)據(jù)發(fā)射完成,此時(shí)才會(huì)將onError提交給訂閱者。
例如:一個(gè)界面有兩個(gè)網(wǎng)絡(luò)接口請(qǐng)求

//這個(gè)請(qǐng)求故意延時(shí)5秒再發(fā)送->最后測(cè)試結(jié)果發(fā)現(xiàn),并不是searchObservable等待mobileObservable5秒后再發(fā)送,目的驗(yàn)證無序的概念
Observable mobileObservable = Observable.timer(5, TimeUnit.SECONDS).flatMap(new Function>() {
            @Override
            public ObservableSource apply(@NonNull Long aLong) throws Exception {
                return EasyHttp.get("http://apis.juhe.cn/mobile/get")
                        .params("phone", "18688994275")
                        .params("dtype", "json")
                        .params("key", "5682c1f44a7f486e40f9720d6c97ffe4")
                        .execute(new CallClazzProxy, ResultBean>(ResultBean.class) {
                        });
            }
        });

        Observable searchObservable = EasyHttp.get("/ajax.php")
                .baseUrl("http://fy.iciba.com")
                .params("a", "fy")
                .params("f", "auto")
                .params("t", "auto")
                .params("w", "hello world")
                //采用代理
                .execute(new CallClazzProxy, Content>(Content.class) {
                });
        //Observable.merge(mobileObservable,searchObservable).subscribe(new BaseSubscriber() {
        Observable.mergeDelayError(mobileObservable,searchObservable).subscribe(new BaseSubscriber() {
            @Override
            public void onError(ApiException e) {
                showToast(e.getMessage());
            }

            @Override
            public void onNext(@NonNull Object object) {
                //為什么用Object接收,因?yàn)閮蓚€(gè)接口請(qǐng)求返回的數(shù)據(jù)類型不是一樣的,如果是一樣的就用具體的對(duì)象接收就可以了,
                // 不再需要instanceof麻煩的判斷
                if (object instanceof ResultBean) {//mobileObservable 返回的結(jié)果
                    //處理  ResultBean邏輯
                } else if (object instanceof Content) {
                    //處理  Content邏輯
                }
                showToast(object.toString());
            }
        });

其中提到一個(gè)概念:合并的Observable發(fā)射的數(shù)據(jù)交錯(cuò),也就是發(fā)射的數(shù)據(jù)無序,怎么理解它呢?例如:代碼中merge(mobileObservable,searchObservable)合并的mobileObservable和searchObservable,其中mobileObservable在前,并不代表訂閱的subscribe->onNext(@NonNull Object object) 就先返回來數(shù)據(jù),也可能是合并的searchObservable數(shù)據(jù)先返回回來。

延伸講解,剛才講解了merge操作符是無序的,如果想保證有序執(zhí)行怎么辦呢,采用Rxjava的concat操作符

看完場(chǎng)景七和場(chǎng)景八:merge和zip的區(qū)別到底是什么呢?

merge和zip都是將多個(gè)Observalbe發(fā)射的數(shù)據(jù)項(xiàng),合并到一個(gè)Observable中再發(fā)射出去。只是在發(fā)射的結(jié)果上有所不同。例如有3個(gè)網(wǎng)絡(luò)請(qǐng)求的Observalbe,zip是等待這3個(gè)請(qǐng)求都完成后才一起返回,既onNext調(diào)用1次。merge是3個(gè)Observalbe分別返回,而且無序,既onNext調(diào)用3次,相當(dāng)于把3個(gè)本來分散的網(wǎng)絡(luò)請(qǐng)求。寫在同一個(gè)地方合并起來執(zhí)行。

merge、mergeDelayError都是合并,但是需要注意二者區(qū)別。

merge合并的請(qǐng)求,如果有一個(gè)接口報(bào)錯(cuò)了,就立馬報(bào)錯(cuò),會(huì)終止整個(gè)流,另外的接口也不會(huì)請(qǐng)求。

mergeDelayError合并的請(qǐng)求,如果有一個(gè)接口報(bào)錯(cuò)了,會(huì)延遲錯(cuò)誤處理,后面的接口會(huì)繼續(xù)執(zhí)行沒有被中斷。

場(chǎng)景九:避免重復(fù)請(qǐng)求

這里主要是講解RxEasyHttp如何結(jié)合rxbinding庫compile "com.jakewharton.rxbinding2:rxbinding:2.0.0"來使用。對(duì)rxbinding庫不了解的,可以自己去學(xué)習(xí)一下,這里不詳細(xì)介紹。在頁面請(qǐng)求中可能操作太快導(dǎo)致同一個(gè)網(wǎng)絡(luò)請(qǐng)求重復(fù)執(zhí)行,這里結(jié)合view來說明,點(diǎn)擊一個(gè)按鈕去請(qǐng)求網(wǎng)絡(luò),點(diǎn)擊太快就會(huì)重復(fù)執(zhí)行-界面防抖。
避免重復(fù)請(qǐng)求:利用Rxjavad的throttleFirst操作符。
throttleFirst:會(huì)定期發(fā)射這個(gè)時(shí)間段里源Observable發(fā)射的第一個(gè)數(shù)據(jù)。
例如:點(diǎn)擊按鈕去請(qǐng)求網(wǎng)絡(luò),1s內(nèi)避免點(diǎn)擊過快重復(fù)請(qǐng)求

        RxView.clicks(view).throttleFirst(1, TimeUnit.SECONDS).flatMap(new Function>() {
            @Override
            public ObservableSource apply(@NonNull Object o) throws Exception {
                return EasyHttp.get("http://apis.juhe.cn/mobile/get")
                        .params("phone", "18688994275")
                        .params("dtype", "json")
                        .params("key", "5682c1f44a7f486e40f9720d6c97ffe4")
                        .execute(new CallClazzProxy, ResultBean>(ResultBean.class) {
                        });
            }
        }).subscribe(new BaseSubscriber() {
            @Override
            public void onError(ApiException e) {
                showToast(e.getMessage());
            }

            @Override
            public void onNext(@NonNull ResultBean resultBean) {
                showToast(resultBean.toString());
            }
        });
場(chǎng)景十:減少頻繁的網(wǎng)絡(luò)請(qǐng)求

這里也是主要講解RxEasyHttp如何結(jié)合rxbinding庫compile "com.jakewharton.rxbinding2:rxbinding:2.0.0"來使用。對(duì)rxbinding庫不了解的,可以自己去學(xué)習(xí)一下,這里不介紹用法。像即時(shí)搜索功能,在輸入框中輸入內(nèi)容,實(shí)時(shí)搜索結(jié)果展示。
減少頻繁的網(wǎng)絡(luò)請(qǐng)求:利用Rxjavad的debounce操作符。
debounce:對(duì)源Observable每產(chǎn)生一個(gè)結(jié)果后,如果在規(guī)定的間隔時(shí)間內(nèi)沒有別的結(jié)果產(chǎn)生,則把這個(gè)結(jié)果提交給訂閱者處理,否則忽略該結(jié)果。簡單的理解就是:當(dāng)N個(gè)結(jié)點(diǎn)發(fā)生的時(shí)間太靠近(即發(fā)生的時(shí)間差小于設(shè)定的值T),debounce就會(huì)自動(dòng)過濾掉前N-1個(gè)結(jié)點(diǎn)。
例如:即時(shí)搜索,避免每輸入(刪除)一個(gè)字就做一次請(qǐng)求,500毫秒才讓它去請(qǐng)求一次網(wǎng)絡(luò),這樣可以避免數(shù)據(jù)混亂,也優(yōu)了app性能。

        Disposable mDisposable = RxTextView.textChangeEvents(mEditText)
                .debounce(500, TimeUnit.MILLISECONDS).filter(new Predicate() {
                    @Override
                    public boolean test(@NonNull TextViewTextChangeEvent textViewTextChangeEvent) throws Exception {
                        // 過濾,把輸入字符串長度為0時(shí)過濾掉
                        String key = textViewTextChangeEvent.text().toString();
                        //這里可以對(duì)key進(jìn)行過濾的判斷邏輯
                        return key.trim().length() > 0;
                    }
                }).flatMap(new Function>() {
                    @Override
                    public ObservableSource apply(@NonNull TextViewTextChangeEvent textViewTextChangeEvent) throws Exception {
                        String key = textViewTextChangeEvent.text().toString();
                        Log.d("test", String.format("Searching for: %s", textViewTextChangeEvent.text().toString()));
                        return EasyHttp.get("/ajax.php")
                                .baseUrl("http://fy.iciba.com")
                                .params("a", "fy")
                                .params("f", "auto")
                                .params("t", "auto")
                                .params("w", key)
                                //采用代理
                                .execute(new CallClazzProxy, Content2>(Content2.class) {
                                });
                    }
                }).subscribeWith(new BaseSubscriber() {
                    @Override
                    protected void onStart() {
                    }

                    @Override
                    public void onError(ApiException e) {
                        mTextView.setText(e.getMessage());
                    }

                    @Override
                    public void onNext(@NonNull Content2 content) {
                        mTextView.setText(content.toString());
                    }
                });
         //取消請(qǐng)求
         //EasyHttp.cancelSubscription(mDisposable);
場(chǎng)景十一:網(wǎng)絡(luò)數(shù)據(jù)緩存

網(wǎng)絡(luò)數(shù)據(jù)緩存在RxEasyHttp網(wǎng)絡(luò)庫中已經(jīng)封裝了,也就是開發(fā)者在使用網(wǎng)絡(luò)庫過程中不必關(guān)心緩存具體的實(shí)現(xiàn),通過RxEasyHttp庫文檔講解調(diào)用一些配置參數(shù)就可以實(shí)現(xiàn)需要的緩存功能了。這里主要講解的是不使用okhttp和Retrofit的緩存,而是介紹自己如何封裝緩存。RxEasyHttp網(wǎng)絡(luò)庫除了支持無緩存和默認(rèn)的http緩存之外,又提供了其它6種場(chǎng)景緩存:
FIRSTREMOTE:先請(qǐng)求網(wǎng)絡(luò),請(qǐng)求網(wǎng)絡(luò)失敗后再加載緩存
FIRSTCACHE:先加載緩存,緩存沒有再去請(qǐng)求網(wǎng)絡(luò)
ONLYREMOTE:僅加載網(wǎng)絡(luò),但數(shù)據(jù)依然會(huì)被緩存
ONLYCACHE:只讀取緩存,緩存沒有會(huì)返回null
CACHEANDREMOTE:先使用緩存,不管是否存在,仍然請(qǐng)求網(wǎng)絡(luò),CallBack會(huì)回調(diào)兩次.
CACHEANDREMOTEDISTINCT:先使用緩存,不管是否存在,仍然請(qǐng)求網(wǎng)絡(luò),CallBack回調(diào)不一定是兩次,如果發(fā)現(xiàn)請(qǐng)求的網(wǎng)絡(luò)數(shù)據(jù)和緩存數(shù)據(jù)是一樣的,就不會(huì)再返回網(wǎng)絡(luò)的回調(diào),既回調(diào)一次。否則不相同仍然會(huì)回調(diào)兩次。(目的是為了防止數(shù)據(jù)沒有發(fā)生變化,也需要回調(diào)兩次導(dǎo)致界面無用的重復(fù)刷新)
如果對(duì)這部分源碼敢興趣的請(qǐng)查看RxEasyHttp源碼,由于此部分涉及的知識(shí)點(diǎn)和內(nèi)容比較多,篇幅問題,準(zhǔn)備在下一篇文章中多帶帶介紹網(wǎng)絡(luò)數(shù)據(jù)緩存的各大場(chǎng)景實(shí)現(xiàn),敬請(qǐng)期待!

結(jié)語

到這里幾大常用的RxEasyHttp網(wǎng)絡(luò)庫結(jié)合Rxjava2場(chǎng)景的例子已經(jīng)介紹完了,也證明了RxEasyHttp網(wǎng)絡(luò)庫與Rxjava2是可以完美結(jié)合的,在實(shí)際開發(fā)運(yùn)用中的場(chǎng)景肯定有很多種,例子是怎么也舉不完的,需要靈活運(yùn)用,如何寫這一個(gè)自己的場(chǎng)景呢,我覺得需要如下幾點(diǎn):

充分了解自己的需求(需要的場(chǎng)景),明確目的(例如:我是想做一個(gè)網(wǎng)絡(luò)輪詢的,最終需要訂閱者給我返回什么);

熟悉Rxjava操作符,看看哪個(gè)操作符是符合需求場(chǎng)景的,或者多個(gè)操作符串聯(lián)起來是符合需求場(chǎng)景,了解每個(gè)操作符單個(gè)用法和訂閱返回的值;

準(zhǔn)備好網(wǎng)絡(luò)請(qǐng)求,保證網(wǎng)絡(luò)請(qǐng)求對(duì)象返回的是Observable,這樣與Rxjava結(jié)合才能成為可能;

將Rxjava單個(gè)操作符或者多個(gè)操作符,與網(wǎng)絡(luò)庫的Observable進(jìn)行結(jié)合,這里面可能是需要flatMap,Function等操作;

文章難免有疏漏之處,如果您有任何疑議,請(qǐng)反饋給我,謝謝!同時(shí)大家有與網(wǎng)絡(luò)相關(guān)更好更常用的場(chǎng)景請(qǐng)推薦給我,我會(huì)繼續(xù)完善。喜歡請(qǐng)點(diǎn)贊,謝謝!

源碼下載

對(duì)場(chǎng)景應(yīng)用感興趣的小伙伴們可以將Demo下載下來進(jìn)行參考。
項(xiàng)目地址

https://github.com/zhou-you/RxEasyHttp
引用文字
歡迎加入我的圈子

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/61915.html

相關(guān)文章

  • 網(wǎng)絡(luò)庫與Rxjava2結(jié)合常見使用場(chǎng)景介紹

    摘要:本文主要是講與怎么結(jié)合的,也不會(huì)的操作符深入講解,不然就脫離了本文的重心廢話不多說了,一起來看看是如何使用的。延遲請(qǐng)求利用的操作符。 前言 之前在github開源過一個(gè)網(wǎng)絡(luò)庫RxEasyHttp,這是一款基于RxJava2+Retrofit2實(shí)現(xiàn)簡單易用的網(wǎng)絡(luò)請(qǐng)求框架。在這里對(duì)網(wǎng)絡(luò)庫的用法就不做過多介紹,感興趣的可以去了解下。在使用過程中一些網(wǎng)友反饋不知道怎么結(jié)合Rxjava2來實(shí)現(xiàn)一...

    coolpail 評(píng)論0 收藏0
  • JAVA筆記 - 收藏集 - 掘金

    摘要:動(dòng)態(tài)代理個(gè)經(jīng)紀(jì)人如何代理個(gè)明星掘金在代理模式女朋友這么漂亮,你缺經(jīng)紀(jì)人嗎中我們用寶強(qiáng)的例子介紹了靜態(tài)代理模式的概念。掘金使用從頭創(chuàng)建一個(gè),這種方法比較簡單。 動(dòng)態(tài)代理:1 個(gè)經(jīng)紀(jì)人如何代理 N 個(gè)明星 - Android - 掘金在 代理模式:女朋友這么漂亮,你缺經(jīng)紀(jì)人嗎? 中我們用寶強(qiáng)的例子介紹了靜態(tài)代理模式的概念。 本來我的目的是通過大家耳熟能詳?shù)睦觼砑由罾斫?,但是有些網(wǎng)友指責(zé)...

    kamushin233 評(píng)論0 收藏0
  • Java進(jìn)階之路

    摘要:探索專為而設(shè)計(jì)的將探討進(jìn)行了何種改進(jìn),以及這些改進(jìn)背后的原因。關(guān)于最友好的文章進(jìn)階前言之前就寫過一篇關(guān)于最友好的文章反響很不錯(cuò),由于那篇文章的定位就是簡單友好,因此盡可能的摒棄復(fù)雜的概念,只抓住關(guān)鍵的東西來講,以保證大家都能看懂。 周月切換日歷 一個(gè)可以進(jìn)行周月切換的日歷,左右滑動(dòng)的切換月份,上下滑動(dòng)可以進(jìn)行周,月不同的視圖切換,可以進(jìn)行事件的標(biāo)記,以及節(jié)假日的顯示,功能豐富 Andr...

    sushi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<