這篇文章寫的內(nèi)容是從資料上復(fù)制下來(lái)的管宵。應(yīng)該是RxJava的官方資料翻譯過(guò)來(lái)的文件,忘記原出處了低散。
Subject
Subject可以看成是一個(gè)橋梁或者代理桨昙,在某些ReactiveX實(shí)現(xiàn)中( 如RxJava) ,它同時(shí)充當(dāng)了Observer和Observable的角色措左。因?yàn)樗且粋€(gè)Observer依痊,它可以訂閱一個(gè)或多個(gè)Observable;又因?yàn)樗且粋€(gè)Observable怎披,它可以轉(zhuǎn)發(fā)它收到(Observe)的數(shù)據(jù)胸嘁,也可以發(fā)射新的數(shù)據(jù)。
由于一個(gè)Subject訂閱一個(gè)Observable凉逛,它可以觸發(fā)這個(gè)Observable開始發(fā)射數(shù)據(jù)( 如果那個(gè)Observable是"冷"的--就是說(shuō)性宏,它等待有訂閱才開始發(fā)射數(shù)據(jù)) 。因此有這樣的效果状飞,Subject可以把原來(lái)那個(gè)"冷"的Observable變成"熱"的毫胜。
Subject的種類
針對(duì)不同的場(chǎng)景一共有四種類型的Subject书斜。他們并不是在所有的實(shí)現(xiàn)中全部都存在,而且一些實(shí)現(xiàn)使用其它的命名約定( 例如酵使,在RxScala中Subject被稱作PublishSubject) 荐吉。
AsyncSubject
一個(gè)AsyncSubject只在原始Observable完成后,發(fā)射來(lái)自原始Observable的最后一個(gè)值口渔。( 如果原始Observable沒有發(fā)射任何值样屠,AsyncObject也不發(fā)射任何值) 它會(huì)把這最后一個(gè)值發(fā)射給任何后續(xù)的觀察者。
然而缺脉,如果原始的Observable因?yàn)榘l(fā)生了錯(cuò)誤而終止痪欲,AsyncSubject將不會(huì)發(fā)射任何數(shù)據(jù),只是簡(jiǎn)單的向前傳遞這個(gè)錯(cuò)誤通知 枪向。
BehaviorSubject
當(dāng)觀察者訂閱BehaviorSubject時(shí)勤揩,它開始發(fā)射原始Observable最近發(fā)射的數(shù)據(jù)( 如果此時(shí)還沒有收到任何數(shù)據(jù)咧党,它會(huì)發(fā)射一個(gè)默認(rèn)值) 秘蛔,然后繼續(xù)發(fā)射其它任何來(lái)自原始Observable的數(shù)據(jù) 。
然而傍衡,如果原始的Observable因?yàn)榘l(fā)生了一個(gè)錯(cuò)誤而終止深员,BehaviorSubject將不會(huì)發(fā)射任何數(shù)據(jù),只是簡(jiǎn)單的向前傳遞這個(gè)錯(cuò)誤通知蛙埂。
PublishSubject
PublishSubject只會(huì)把在訂閱發(fā)生的時(shí)間點(diǎn)之后來(lái)自原始Observable的數(shù)據(jù)發(fā)射給觀察者倦畅。需要注意的是,PublishSubject可能會(huì)一創(chuàng)建完成就立刻開始發(fā)射數(shù)據(jù)( 除非你可以阻止它發(fā)生) 绣的,因此這里有一個(gè)風(fēng)險(xiǎn):在Subject被創(chuàng)建后到有觀察者訂閱它之前這個(gè)時(shí)間段內(nèi)叠赐,一個(gè)或多個(gè)數(shù)據(jù)可能會(huì)丟失。如果要確保來(lái)自原始Observable的所有數(shù)據(jù)都被分發(fā)屡江,你需要這樣做:或者使用Create創(chuàng)建那個(gè)Observable以便手動(dòng)給它引入"冷"Observable的行為( 當(dāng)所有觀察者都已經(jīng)訂閱時(shí)才開始發(fā)射數(shù)據(jù)) 芭概,或者改用ReplaySubject。
如果原始的Observable因?yàn)榘l(fā)生了一個(gè)錯(cuò)誤而終止惩嘉,PublishSubject將不會(huì)發(fā)射任何數(shù)據(jù)罢洲,只是簡(jiǎn)單的向前傳遞這個(gè)錯(cuò)誤通知。
ReplaySubject
ReplaySubject會(huì)發(fā)射所有來(lái)自原始Observable的數(shù)據(jù)給觀察者文黎,無(wú)論它們是何時(shí)訂閱的惹苗。也有其它版本的ReplaySubject,在重放緩存增長(zhǎng)到一定大小的時(shí)候或過(guò)了一段時(shí)間后會(huì)丟棄舊的數(shù)據(jù)( 原始Observable發(fā)射的) 耸峭。
如果你把ReplaySubject當(dāng)作一個(gè)觀察者使用桩蓉,注意不要從多個(gè)線程中調(diào)用它的onNext方法( 包括其它的on系列方法),這可能導(dǎo)致同時(shí)(非順序) 調(diào)用劳闹,這會(huì)違反Observable協(xié)議触机,給Subject的結(jié)果增加了不確定性帚戳。
RxJava的對(duì)應(yīng)類
假設(shè)你有一個(gè)Subject,你想把它傳遞給其它的代理或者暴露它的Subscriber接口儡首,你可以調(diào)用它的asObservable方法片任,這個(gè)方法返回一個(gè)Observable。具體使用方法可以參考Javadoc文檔蔬胯。
串行化
如果你把 Subject 當(dāng)作一個(gè) Subscriber 使用对供,注意不要從多個(gè)線程中調(diào)用它的onNext方法( 包括其它的on系列方法) ,這可能導(dǎo)致同時(shí)( 非順序) 調(diào)用氛濒,這會(huì)違反Observable協(xié)議产场,給Subject的結(jié)果增加了不確定性。
要避免此類問(wèn)題舞竿,你可以將 Subject 轉(zhuǎn)換為一個(gè) SerializedSubject 京景,類似于這樣:
mySafeSubject = new SerializedSubject( myUnsafeSubject )