Rxjava2-小白入門(三)

前言

繼續(xù)上篇的Rxjava2的入門實(shí)例缝呕,把剩下的運(yùn)用Rxjava的實(shí)例講下枫夺,首先要說名下本文會(huì)用到Rxbinding的知識(shí)昭殉,他相當(dāng)于Rxjava的輔助工具忙干,在引入他的時(shí)候會(huì)自動(dòng)幫我們引入Rxjava上祈,在本文中我就不具體講解了培遵,用法比較簡單,沒解除的同學(xué)找些相關(guān)的文章登刺,相信很快就能上手的荤懂,。在這里我把依賴寫下

compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0'

這個(gè)版本默認(rèn)引入的是Rxjava2.0.2的版本


Rxjava2的操作符

  • create
  • just
  • fromArray
  • map
  • flatMap
  • zip
  • filter
  • time
  • merge
  • retry
  • retryWhen
  • range
  • Interval
  • ...

Rxjava2的使用場(chǎng)景

  • 登陸后獲取用戶信息
  • 關(guān)鍵詞搜索
  • 防止按鈕重復(fù)點(diǎn)擊
  • 購物車合并本地和網(wǎng)絡(luò)數(shù)據(jù)
  • 發(fā)送驗(yàn)證碼倒計(jì)時(shí)

關(guān)鍵詞搜索

一般情況我們監(jiān)聽EditText控件,當(dāng)值發(fā)生改變?nèi)フ?qǐng)求搜索接口塘砸,如下:


a: 可能導(dǎo)致很多沒有意義的請(qǐng)求,耗費(fèi)用戶流量(因?yàn)榭丶闹得扛囊淮瘟⒓淳蜁?huì)去請(qǐng)求網(wǎng)絡(luò)节仿,而且只是最后輸入的關(guān)鍵字是有用的)

b:可能導(dǎo)致最終搜索的結(jié)果不是用戶想要的.
例如,用戶一開始輸入關(guān)鍵字’AB’ 這個(gè)時(shí)候出現(xiàn)兩個(gè)請(qǐng)求, 一個(gè)請(qǐng)求是A關(guān)鍵字, 一個(gè)請(qǐng)求是AB關(guān)鍵字. 表面上是’A’請(qǐng)求先發(fā)出去, ‘AB’請(qǐng)求后發(fā)出去. 如果后發(fā)出去的’AB’請(qǐng)求先返回, ‘A’請(qǐng)求后返回,那么’A’請(qǐng)求后的結(jié)果將會(huì)覆蓋’AB’請(qǐng)求的結(jié)果. 從而導(dǎo)致搜索結(jié)果不正確.

在寫代碼之前我們先介紹下我們要用到的操作符debounce它屬于過濾操作符



這是官方文檔給出的解釋,從解釋中我們也不難看出他的用法掉蔬。那么下面我在實(shí)例中去使用吧廊宪!

 RxTextView.textChanges(mView)//通過Rxbinding的textChanges()監(jiān)聽AutoCompleteTextView文字的變化,他是一個(gè)Obervable對(duì)象
                .debounce(200, TimeUnit.MILLISECONDS)//利用debounce操作符延遲發(fā)送 TimeUnit.MILLISECONDS(毫秒)指定一個(gè)參數(shù)的單位
                .subscribeOn(AndroidSchedulers.mainThread())//通過Rxbinding監(jiān)聽控件必須在主線程
                .filter(new Predicate<CharSequence>() {
                    @Override
                    public boolean test(CharSequence charSequence) throws Exception {
                        //過濾為空的數(shù)據(jù) 避免多余請(qǐng)求
                        return charSequence.toString().trim().length() > 0;
                    }
                })
                .flatMap(new Function<CharSequence, ObservableSource<List<String>>>() {
                    @Override
                    public ObservableSource<List<String>> apply(CharSequence charSequence) throws Exception {
                        Log.d(TAG, "apply: " + charSequence.toString());
                        String request = charSequence.toString().trim();//輸入的內(nèi)容
                        /**
                         * 通過輸入的內(nèi)容request發(fā)起網(wǎng)絡(luò)請(qǐng)求
                         * 返回一個(gè)模糊匹配的字符串集合用于顯示
                         * 這里我們構(gòu)建一個(gè)假的數(shù)據(jù)
                         */
                        List<String> mList = new ArrayList<String>();
                        mList.add("abc");
                        mList.add("abd");
                        mList.add("abop");
                        mList.add("ac");
                        return Observable.just(mList);
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<List<String>>() {
                    @Override
                    public void accept(List<String> strings) throws Exception {
                        Log.d(TAG, "accept: " + strings.toString());
                        ArrayAdapter<String> adapter = new ArrayAdapter<String>
                                (getApplicationContext(), android.R.layout.simple_list_item_1, android.R.id.text1, strings);
                        mView.setAdapter(adapter);
                    }
                });
    }

這就是一個(gè)簡單模擬關(guān)鍵詞搜索的實(shí)例,但是雖然我們滿足了上面提到的要求a女轿,但是要求b也就是可能返回的數(shù)據(jù)先后不同可能會(huì)導(dǎo)致結(jié)果不是們想要的箭启,那么該怎么處理呢?通過文檔我們找到了這樣一個(gè)操作符switchMap蛉迹,讓我們來看看他的使用



這個(gè)操作符正好符合我們的業(yè)務(wù)要求傅寡,同時(shí)他也屬于變換操作符,所以我們自需要把flatmap改成switchMap就可以了北救。這樣我們2者的區(qū)別和debounce的用法結(jié)合實(shí)例是不是更加深刻呢荐操?


防止按鈕重復(fù)(連續(xù))點(diǎn)擊

在實(shí)際應(yīng)用中可能在提交信息,登錄的時(shí)候每次點(diǎn)擊按鈕就會(huì)發(fā)送網(wǎng)絡(luò)請(qǐng)求珍策,當(dāng)網(wǎng)絡(luò)比較慢的時(shí)候或是其他原因已經(jīng)請(qǐng)求網(wǎng)路只是返回的數(shù)據(jù)比較慢托启,當(dāng)我們連續(xù)點(diǎn)擊就會(huì)連續(xù)的發(fā)送請(qǐng)求,這樣的結(jié)果必然不是我們想要的攘宙。

ThrottleFirst:
允許設(shè)置一個(gè)時(shí)間長度屯耸,之后它會(huì)發(fā)送固定時(shí)間長度內(nèi)的第一個(gè)事件拐迁,而屏蔽其它事件,在間隔達(dá)到設(shè)置的時(shí)間后疗绣,可以再發(fā)送下一個(gè)事件

這個(gè)操作符就很好的解決了這個(gè)問題

 RxView.clicks(mButton).throttleFirst(2, TimeUnit.SECONDS).subscribe(new Consumer<Object>() {
            @Override
            public void accept(Object o) throws Exception {
                SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String dateStr = dateformat.format(System.currentTimeMillis());
                Log.d(TAG, "accept: "+dateStr);
            }
        });

我在不斷點(diǎn)擊的情況下线召,輸出結(jié)果:

10-08 21:51:07.008 3950-3950/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 2017-10-08 21:51:07
10-08 21:51:09.168 3950-3950/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 2017-10-08 21:51:09
10-08 21:51:11.308 3950-3950/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 2017-10-08 21:51:11
10-08 21:51:13.398 3950-3950/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 2017-10-08 21:51:13

可以看到2秒內(nèi)自能點(diǎn)擊一次。

注意:此時(shí)可以用ThrottleFirst也可以用debounce 效果是一樣的 但是 ThrottleFirst發(fā)出的是第一個(gè) debounce 發(fā)出的是最后一個(gè) 都是保證單位時(shí)間內(nèi)只能發(fā)送一次 但是原理還是有些不同的多矮,過會(huì)2個(gè)例子也不難比較區(qū)別


購物車合并本地和網(wǎng)絡(luò)數(shù)據(jù)

現(xiàn)在有這么一種情況缓淹,你在上班的時(shí)候偷偷用電腦上淘寶準(zhǔn)備買衣服看重了一雙鞋子和衣服加入購物車。在回家的路上用手機(jī)又加入購物車褲子和襯衫工窍。等你回家的時(shí)候準(zhǔn)備用手機(jī)購買割卖,購物車?yán)飸?yīng)該是所有的商品都在的,那么我們就需要把手機(jī)的和web端合并在一起并展示患雏。這時(shí)我們就可以用到merge操作符鹏溯。

在使用前我們先了解下merge:



關(guān)于merge的官方文檔和圖片分析還是比較簡單的。不理解的話等我們講完實(shí)例后回頭在來看看淹仑。下面是具體代碼:

  mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {

                /*兩者合并*/
                Observable.merge(getObervableLocal(), getObervableWeb()).subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread()).
                        subscribe(new Consumer<List<User>>() {
                            @Override
                            public void accept(List<User> users) throws Exception {
                                for (int i = 0; i <users.size() ; i++) {
                                    Log.d(TAG, "accept: "+users.get(i).getName());
                                }
                            }
                        });
            }
        });
    }
    /**
     * 本地?cái)?shù)據(jù)(從數(shù)據(jù)庫中取)
     *
     * @return 返回本地?cái)?shù)據(jù)(手機(jī)端)的購物車信息
     */
    public Observable<List<User>> getObervableLocal() {
        //用User對(duì)象代表商品實(shí)例
        //我們用手機(jī)購買一般數(shù)據(jù)會(huì)緩存到手機(jī)的數(shù)據(jù)庫當(dāng)中
        User user = new User("褲子", "16元");
        User user1 = new User("襯衫", "18元");

        List<User> mList = new ArrayList<>();
        mList.add(user);
        mList.add(user1);
        return Observable.just(mList);
    }

    /**
     * web數(shù)據(jù)(從網(wǎng)絡(luò)中請(qǐng)求)
     *
     * @return 返回網(wǎng)絡(luò)數(shù)據(jù)
     */
    public Observable<List<User>> getObervableWeb() {
        //網(wǎng)絡(luò)請(qǐng)求 查看服務(wù)器購物車是否有數(shù)據(jù)
        User user = new User("衣服", "20元");
        User user1 = new User("褲子", "22元");

        List<User> mList = new ArrayList<>();//模擬請(qǐng)求返回的數(shù)據(jù)
        mList.add(user);
        mList.add(user1);
        return Observable.fromArray(mList).subscribeOn(Schedulers.io());//網(wǎng)絡(luò)請(qǐng)求在子線程
    }


運(yùn)行結(jié)果:

10-09 12:39:08.678 11602-11602/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 褲子
10-09 12:39:08.678 11602-11602/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 襯衫
10-09 12:39:08.678 11602-11602/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 衣服
10-09 12:39:08.678 11602-11602/com.example.ggxiaozhi.rxjava D/Main3Activity: accept: 褲子

注意其實(shí)合并的操作符還有zip和zipWith丙挽,其實(shí)2者差不多只是參數(shù)不一樣。用法也是比較簡單zip操作符也可以看看這篇文章匀借。實(shí)際操作下會(huì)更加深印象颜阐。這里我就不咱代碼了。


發(fā)送驗(yàn)證碼倒計(jì)時(shí)

這個(gè)實(shí)例我們用到Interval操作符:



具體代碼操作:



所有的實(shí)例都講完了我們?cè)诳聪聄etryWhen和retry吓肋,range操作符凳怨。

retry操作符

retryWhen和retry的主要區(qū)別概括來說就是retryWhen將錯(cuò)誤的信息發(fā)送下去(出錯(cuò)了就發(fā)送錯(cuò)誤信息),retry是出錯(cuò)了會(huì)先嘗試重新訂閱再發(fā)送一變是鬼,當(dāng)達(dá)到設(shè)置的重試次數(shù)時(shí)還沒有成功才會(huì)發(fā)出錯(cuò)誤的信息


總結(jié):感覺文章寫的好亂肤舞,主要的原因是因?yàn)楸旧硪苍趯W(xué)習(xí)中很多東西總結(jié)的不夠透徹,雖然看了很多文章但是自己寫起來還是會(huì)亂亂的均蜜,以后會(huì)努力希望一次比一次好李剖,作為小白,這是我自身的學(xué)習(xí)筆記囤耳。如果有錯(cuò)誤希望大家指出篙顺,我將不勝感激。

推薦文章:
Rxjava2
RxJava2操作符
RxJava/RxAndroid 使用實(shí)例實(shí)踐
Rxjava2我覺得關(guān)于rxjava2這個(gè)系列真的非常好很值得學(xué)習(xí)

代碼地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末充择,一起剝皮案震驚了整個(gè)濱河市德玫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌聪铺,老刑警劉巖化焕,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異铃剔,居然都是意外死亡撒桨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門键兜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凤类,“玉大人,你說我怎么就攤上這事普气∶瞻蹋” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵现诀,是天一觀的道長夷磕。 經(jīng)常有香客問我,道長仔沿,這世上最難降的妖魔是什么坐桩? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮封锉,結(jié)果婚禮上绵跷,老公的妹妹穿的比我還像新娘。我一直安慰自己成福,他們只是感情好碾局,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著奴艾,像睡著了一般净当。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蕴潦,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天像啼,我揣著相機(jī)與錄音,去河邊找鬼品擎。 笑死埋合,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的萄传。 我是一名探鬼主播甚颂,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼秀菱!你這毒婦竟也來了振诬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤衍菱,失蹤者是張志新(化名)和其女友劉穎赶么,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脊串,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡辫呻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年清钥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片放闺。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡祟昭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怖侦,到底是詐尸還是另有隱情篡悟,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布匾寝,位于F島的核電站搬葬,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏艳悔。R本人自食惡果不足惜急凰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望很钓。 院中可真熱鬧香府,春花似錦、人聲如沸码倦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽袁稽。三九已至勿璃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間推汽,已是汗流浹背补疑。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留歹撒,地道東北人莲组。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像暖夭,于是被迫代替她去往敵國和親锹杈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,727評(píng)論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理迈着,服務(wù)發(fā)現(xiàn)竭望,斷路器,智...
    卡卡羅2017閱讀 134,626評(píng)論 18 139
  • 前言 上篇文章我們主要講解了觀察者模式裕菠。那么這節(jié)課我們主要講解Rxjava2的基本使用和操作符咬清。其實(shí)網(wǎng)上的關(guān)于Rx...
    g小志閱讀 550評(píng)論 0 2
  • RxJava2 實(shí)戰(zhàn)系列文章 RxJava2 實(shí)戰(zhàn)知識(shí)梳理(1) - 后臺(tái)執(zhí)行耗時(shí)操作,實(shí)時(shí)通知 UI 更新RxJ...
    澤毛閱讀 8,914評(píng)論 23 44
  • 古人把每個(gè)季節(jié)分為三個(gè)段,孟旧烧、仲影钉、季,秋季的三個(gè)月是七粪滤、八斧拍、九月雀扶,對(duì)應(yīng)的是孟秋酱吝、仲秋筷黔、季秋,農(nóng)歷的八月十五正好是仲...
    薛善強(qiáng)閱讀 490評(píng)論 0 1