RxJava+Retrofit (二) 觀(guān)察者模式及Rx基礎(chǔ)概念解釋

本系列的七篇文章(目前完成進(jìn)度:2/7):
1撼嗓、什么響應(yīng)式編程
2绑谣、觀(guān)察者模式及Rx基礎(chǔ)概念解釋
3、RxJava深入淺出
4程梦、RxJava+Retrofit 的結(jié)合
5点把、RxJava的高階使用
6、Retrofit的進(jìn)階應(yīng)用
7屿附、總結(jié)

觀(guān)察者模式

其實(shí)非常簡(jiǎn)單郎逃,就是監(jiān)聽(tīng)。我們?cè)谧鯝ndroid開(kāi)發(fā)的時(shí)候挺份,必定繞不過(guò)的就是給Button設(shè)置監(jiān)聽(tīng)器(你沒(méi)做過(guò)算我輸好吧):

 bn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d("TAG","OnCLick");
            }
        });

在上面的例子中褒翰,匿名內(nèi)部類(lèi)View.OnClickListener就是觀(guān)察者,按鈕bn就是被觀(guān)察者匀泊。一旦被觀(guān)察者被觀(guān)察到“被點(diǎn)擊”這個(gè)事件影暴,觀(guān)察者就會(huì)做出相應(yīng)的反應(yīng)(出log)。
 

 
  
  是的探赫,你已經(jīng)用了很久的觀(guān)察者模式了型宙,只是你不知道而已。
  觀(guān)察者模式的描述應(yīng)該是這樣的:定義一個(gè)被觀(guān)察對(duì)象伦吠,再定義一個(gè)(或多個(gè))觀(guān)察者妆兑,觀(guān)察者時(shí)刻在觀(guān)察著被觀(guān)察對(duì)象的一舉一動(dòng),一旦被觀(guān)察對(duì)象的狀態(tài)發(fā)生了變化毛仪,所有的觀(guān)察者都會(huì)馬上做出反應(yīng)搁嗓。
  
  
  補(bǔ)充一點(diǎn),在現(xiàn)實(shí)的編程中不會(huì)有“時(shí)刻都在觀(guān)察”這種這么蠢的實(shí)現(xiàn)方式的箱靴,所以最好不要將觀(guān)察者模式理解為'觀(guān)察者'時(shí)刻監(jiān)控著'被觀(guān)察者'(雖然語(yǔ)義上這樣的)腺逛,應(yīng)該理解為:'被觀(guān)察者'其實(shí)是‘通知者’,自己有點(diǎn)什么狀態(tài)變化(或者是什么事情發(fā)生)就馬上通知"觀(guān)察者"(就是實(shí)現(xiàn)約定好的)衡怀,然后觀(guān)察者再對(duì)此做出反應(yīng)棍矛。(所以我個(gè)人更傾向于將“觀(guān)察者模式”稱(chēng)為“通知者模式”)
  
  
  
  回到本系列的第一篇安疗,那個(gè)和全蛋一起工作的你。流水線(xiàn)模式是觀(guān)察者模式嗎够委,是嗎荐类?是的。但是茁帽,請(qǐng)注意玉罐,只有最后的打包員才是觀(guān)察者!E瞬Α吊输!你們這些加工工人并不算是觀(guān)察者,就算是觀(guān)察者铁追,地位也是比打包員的低的h笛恰(此處我是后來(lái)才意識(shí)到的,因而算是一個(gè)錯(cuò)誤)
  為什么這樣說(shuō)脂信,其實(shí)大家可以理解為打包員才是可以睡懶覺(jué)的人癣蟋,當(dāng)然在加工工人沒(méi)事做的時(shí)候也是在睡懶覺(jué)。但是狰闪,就算你們都是在睡懶覺(jué)疯搅,打包員才是“觀(guān)察者”,當(dāng)手機(jī)開(kāi)始在流水線(xiàn)上流動(dòng)的時(shí)候埋泵,流水線(xiàn)只會(huì)通知打包員幔欧,打包員一醒,就會(huì)把你們這些加工工人全部叫醒丽声,幫他干活礁蔗。(需要感受一下打包員和加工工人地位的差距,以及喚醒的時(shí)機(jī))
  
  現(xiàn)在再理一下思路:

  • 流水線(xiàn)是“被觀(guān)察者”雁社,
  • 流動(dòng)著的手機(jī)是“數(shù)據(jù)流”浴井,
  • 打包員是“觀(guān)察者”,
  • 觀(guān)察的事件是“手機(jī)毛坯進(jìn)入流水線(xiàn)”霉撵,
  • 觀(guān)察者的響應(yīng)動(dòng)作是“將沒(méi)有問(wèn)題的手機(jī)打包好磺浙,有問(wèn)題的手機(jī)另行處理”,
  • 訂閱是“事件發(fā)生以后響鈴?fù)ㄖ薄?/li>
  • 至于加工工人徒坡,只是在觀(guān)察者的響應(yīng)動(dòng)作發(fā)生前對(duì)數(shù)據(jù)流的處理撕氧。
      
      
    (Ps,將“被觀(guān)察者”換為“通知者”真的是會(huì)舒服很多)

用RxJava做個(gè)小Demo

例子還是我們的手機(jī)加工喇完,廢話(huà)不多說(shuō)伦泥,直接上代碼:

static void product() {
        Phone[] phones = new Phone[5];
        for (int i = 0; i < phones.length; i++) {
            phones[i] = new Phone(i + "號(hào)iPhone");
        }

        Observable.from(phones)                             //Observable,被觀(guān)察者
                .map(new Func1<Phone, Phone>() {            //裝天線(xiàn)加工
                    @Override
                    public Phone call(Phone phone) {
                        try {
                            Thread.sleep(2000);  
                            //為了體現(xiàn)順序,我給加工設(shè)置了耗時(shí)
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        return phone.change("裝了天線(xiàn)的");
                    }
                })
                .map(new Func1<Phone, Phone>() {            //裝攝像頭加工
                    @Override
                    public Phone call(Phone phone) {
                        return phone.change("裝了攝像頭的不脯、");
                    }
                })
                .subscribe(new Observer<Phone>() {          //Observer府怯,觀(guān)察者訂閱事件
                    @Override
                    public void onCompleted() {
                        System.out.println("搞掂,收工跨新!");
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println("出了點(diǎn)小問(wèn)題");
                    }

                    @Override
                    public void onNext(Phone phone) {
                        System.out.println(phone.show()+"被打包好了");
                    }
                });
    }

輸出結(jié)果是:

裝了攝像頭的、裝了天線(xiàn)的0號(hào)iPhone被打包好了
裝了攝像頭的坏逢、裝了天線(xiàn)的1號(hào)iPhone被打包好了
裝了攝像頭的域帐、裝了天線(xiàn)的2號(hào)iPhone被打包好了
裝了攝像頭的、裝了天線(xiàn)的3號(hào)iPhone被打包好了
裝了攝像頭的是整、裝了天線(xiàn)的4號(hào)iPhone被打包好了
搞掂肖揣,收工!

Process finished with exit code 0

//附浮入,這里的輸出是每?jī)擅胼敵鲆淮?/p>

代碼我放到Gist了龙优,賞臉給個(gè)star可好.

RxJava的基本概念

Observable:被觀(guān)察者,也可解釋為發(fā)射源事秀,或數(shù)據(jù)流就是從這里發(fā)射出來(lái)的彤断;

Observer:觀(guān)察者,接收源,數(shù)據(jù)流就是在這里被接收易迹;

Subscriber:“訂閱者”宰衙,也是接收源,那它跟Observer有什么區(qū)別呢睹欲?Subscriber實(shí)現(xiàn)了Observer接口供炼,比Observer多了一個(gè)最重要的方法unsubscribe( ),用來(lái)取消訂閱窘疮,當(dāng)你不再想接收數(shù)據(jù)了袋哼,可以調(diào)用unsubscribe( )方法停止接收,Observer 在 subscribe() 過(guò)程中,最終也會(huì)被轉(zhuǎn)換成 Subscriber 對(duì)象闸衫,一般情況下涛贯,建議使用Subscriber作為接收源;

Subscription:Observable調(diào)用subscribe( )方法返回的對(duì)象蔚出,同樣有unsubscribe( )方法疫蔓,可以用來(lái)取消訂閱事件;

Action0:RxJava中的一個(gè)接口身冬,它只有一個(gè)無(wú)參call()方法衅胀,且無(wú)返回值,同樣還有Action1酥筝,Action2...Action9等滚躯,Action1封裝了含有 1 個(gè)參的call()方法,即call(T t),Action2封裝了含有 2 個(gè)參數(shù)的call方法掸掏,即call(T1 t1茁影,T2 t2),以此類(lèi)推丧凤;

Func0:與Action0非常相似募闲,也有call()方法,但是它是有返回值的愿待,同樣也有Func0浩螺、Func1...Func9;

關(guān)于A(yíng)ction 和 Func:

先說(shuō)Func吧,在上面的demo中仍侥,我們用到了Func1要出,于是我們?nèi)タ纯碏unc1的源碼:

/**
 * Represents a function with one argument.
 */
public interface Func1<T, R> extends Function {
    R call(T t);
}

非常短吧,只有一個(gè)方法call(T t)农渊,再跑去看看Func2的源碼:

/**
 * Represents a function with two arguments.
 */
public interface Func2<T1, T2, R> extends Function {
    R call(T1 t1, T2 t2);
}

同樣的患蹂,也是只有一個(gè)方法,call(T1 t1,T2 t2)砸紊。
再看回我們的Demo:

 .map(new Func1<Phone, Phone>() {            //裝攝像頭加工
                    @Override
                    public Phone call(Phone phone) {
                        return phone.change("裝了攝像頭的传于、");
                    }
                })

在這里,我們想要做的是“給手機(jī)裝攝像頭”醉顽,我們的預(yù)期是我們提供一個(gè)方法給你格了,你只需要把“還沒(méi)裝攝像頭的手機(jī)”當(dāng)作是一個(gè)參數(shù)輸入到這個(gè)方法里面,然后這個(gè)方法就會(huì)返回“裝了攝像頭的手機(jī)”徽鼎。 (很明顯盛末,這段話(huà)的“你”指的是Rx框架)
  然而,在Java中是沒(méi)有方法指針這種東西否淤,為了達(dá)到“將指定方法傳遞給Rx框架”的目的悄但,設(shè)計(jì)者設(shè)計(jì)了Func和Action。
  我們通過(guò)傳遞Func實(shí)例來(lái)傳遞一個(gè)方法石抡!首先我們先新建一個(gè)Func1實(shí)例檐嚣,然后將我們想要執(zhí)行的方法寫(xiě)到Func1實(shí)例中的call方法中(覆蓋),最后再把這個(gè)實(shí)例傳遞給Rx框架啰扛。Rx框架就會(huì)在指定的時(shí)刻執(zhí)行我們Func1實(shí)例中的call方法嚎京,并把call方法的返回值傳遞到下一個(gè)流程。
  
  大概就是這樣了隐解,通過(guò)傳遞實(shí)例來(lái)傳遞方法在Java中其實(shí)不少見(jiàn)鞍帝,最常見(jiàn)的就是給Button傳遞一個(gè)OnClickListener來(lái)傳遞回調(diào)方法。
  此外煞茫,我們?cè)谑褂肍unc有時(shí)可能不止需要一個(gè)輸入帕涌,可能要0個(gè)輸入就好了摄凡,但有時(shí)需要可能需要2個(gè)、3個(gè)...輸入的話(huà)蚓曼,那該如何亲澡。
  諸君莫方,我們還有Func0纫版、Func1床绪、Func2...肯定有一款適合你。Func后面的數(shù)字表示的是call方法的參數(shù)個(gè)數(shù)其弊,我們只要根據(jù)需要選擇Func接口就可以了(可看上面的兩個(gè)Func接口的源碼癞己,比較出差別)。
  
  
  說(shuō)完Func瑞凑,Action也就差不多了末秃,Action和Func的區(qū)別就在于概页,Action沒(méi)有返回值籽御。

最后

似乎也沒(méi)有什么好總結(jié)的了,就這樣了吧惰匙。


Reference:http://www.reibang.com/p/5e93c9101dc5

未經(jīng)授權(quán)技掏,禁止轉(zhuǎn)載
原文地址:http://www.reibang.com/p/b1bd50afb071

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市项鬼,隨后出現(xiàn)的幾起案子哑梳,更是在濱河造成了極大的恐慌,老刑警劉巖绘盟,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸠真,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡龄毡,警方通過(guò)查閱死者的電腦和手機(jī)吠卷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)沦零,“玉大人祭隔,你說(shuō)我怎么就攤上這事÷凡伲” “怎么了疾渴?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)屯仗。 經(jīng)常有香客問(wèn)我搞坝,道長(zhǎng),這世上最難降的妖魔是什么魁袜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任瞄沙,我火速辦了婚禮己沛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘距境。我一直安慰自己申尼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布垫桂。 她就那樣靜靜地躺著师幕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪诬滩。 梳的紋絲不亂的頭發(fā)上霹粥,一...
    開(kāi)封第一講書(shū)人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音疼鸟,去河邊找鬼后控。 笑死,一個(gè)胖子當(dāng)著我的面吹牛空镜,可吹牛的內(nèi)容都是我干的浩淘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼吴攒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼张抄!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起洼怔,我...
    開(kāi)封第一講書(shū)人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤署惯,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后镣隶,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體极谊,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年安岂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了轻猖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嗜闻,死狀恐怖蜕依,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情琉雳,我是刑警寧澤样眠,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站翠肘,受9級(jí)特大地震影響檐束,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜束倍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一被丧、第九天 我趴在偏房一處隱蔽的房頂上張望盟戏。 院中可真熱鬧,春花似錦甥桂、人聲如沸柿究。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蝇摸。三九已至,卻和暖如春办陷,著一層夾襖步出監(jiān)牢的瞬間貌夕,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工民镜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留啡专,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓制圈,卻偏偏與公主長(zhǎng)得像们童,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子离唐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

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