RxSwift(六) - Subjects、 Variables

Subjects

創(chuàng)建 Observable 序列之后, 要預(yù)先將要發(fā)出的數(shù)據(jù)準(zhǔn)備好, 等到有人訂閱時(shí), 再將數(shù)據(jù)通過 Event 發(fā)出去.

我們希望 Observable 序列能在運(yùn)行時(shí)動(dòng)態(tài)的 獲得 或者說 產(chǎn)生 一個(gè)新數(shù)據(jù), 再通過 Event 發(fā)送出去. 比如: 訂閱一個(gè)輸入框的輸入內(nèi)容, 當(dāng)用戶每輸入一個(gè)字后, 這個(gè)輸入框關(guān)聯(lián)的 Observable 就會(huì)發(fā)出一個(gè)帶有輸入內(nèi)容的 Event, 通知給所有的訂閱者. 這個(gè)就可以使用 Subjects 來實(shí)現(xiàn).

Subjects 基本介紹

(1) Subjects 它是訂閱者, 也是 Obervable :

  • 它是訂閱者, 因?yàn)樗軌騽?dòng)態(tài)的接收新的值
  • 它是一個(gè) Observable, 是因?yàn)楫?dāng) Subjects 有了新的值之后, 就會(huì)通過 Event 將新值發(fā)出給他的所有訂閱者.

(2) 一共有四種 Subjects, 分別是 PublishSubjectBehaviorSubject、ReplaySubject 、 Variable(已廢棄)BehaviorRelay(Variable替代品).

  • 它們都是 Observable, 它們的訂閱者都能收到它們發(fā)出的 Event
  • 直到 Subject 發(fā)出 .complete 或者 .errorEvent 之后, 該 Subject 才會(huì)終結(jié), 不再發(fā)出 .next 事件.
  • 對(duì)于那些在 Subject 終結(jié)后再訂閱的訂閱者, 也能收到一條 .complete 或者 .errorEvent, 告訴這個(gè)新訂閱者, 該 Subject 已經(jīng)終結(jié)
  • 它們的區(qū)別在于 : 當(dāng)一個(gè)新的訂閱者剛訂閱它的時(shí)候,能不能收到 Subject 以前發(fā)出的舊 Event, 如果能,又可以收到多少個(gè) Event.

(3) Subject 的常用方法

  • onNext() : on(.next):的簡(jiǎn)寫, 該方法相當(dāng)于 subject 接收到一個(gè) .next 事件.
  • onError() : on(.error): 的簡(jiǎn)寫, 該方法相當(dāng)于 subject 接收到一個(gè) .error 事件.
  • onCompleted() : on(.completed): 的簡(jiǎn)寫, 該方法相當(dāng)于 subjet 接收到一個(gè) .completed 事件
PublishSubject

(1) 基本介紹

  • PublishSubject 是最普通的 Subjet, 它不需要初始值就能創(chuàng)建.
  • PublishSubject 的訂閱者從開始訂閱的時(shí)間點(diǎn)起,可以收到訂閱 Subject 發(fā)出的新的 Event, 而不會(huì)收到他們?cè)谟嗛喦耙寻l(fā)出的 Event.
PublishSubject.png

(2)案例

override func viewDidLoad() {
        super.viewDidLoad()
        let disposeBag = DisposeBag()
        //創(chuàng)建一個(gè)PublishSubject
        let subject = PublishSubject<String>()
        subject.onNext("11") //此時(shí)沒有訂閱者,不會(huì)輸出
        
        //首次訂閱
        subject.subscribe(onNext: { str in
            print("第一次訂閱: ", str)
        }, onCompleted: {
            print("第一次訂閱 : onCompleted")
        }).disposed(by: disposeBag)
        //有訂閱者,會(huì)輸出
        subject.onNext("22")
        
        subject.subscribe(onNext: { (str) in
            print("第二次訂閱: ", str)
        }, onCompleted: {
            print("第二次訂閱 : onCompleted")
        }).disposed(by: disposeBag)
        subject.onNext("33")//兩個(gè)訂閱者,輸出兩遍
        subject.onCompleted()//結(jié)束兩個(gè)訂閱者,打印兩遍
        subject.onNext("44")//再次發(fā)送event,不會(huì)打印
        //再有新的訂閱者,會(huì)收到onCompleted消息,通知新的訂閱者,該Subject已經(jīng)終結(jié)
        subject.subscribe(onNext: { (str) in
            print("第三次訂閱: ", str)
        }, onCompleted: {
            print("第三次訂閱 : onCompleted")
        }).disposed(by: disposeBag)
}

//輸出結(jié)果 
第一次訂閱:  22
第一次訂閱:  33
第二次訂閱:  33
第一次訂閱 : onCompleted
第二次訂閱 : onCompleted
第三次訂閱 : onCompleted
BehaviorSubject

(1) 基本介紹

  • BehaviorSubject 需要通過一個(gè)默認(rèn)初始值來創(chuàng)建
  • 當(dāng)一個(gè)訂閱者來訂閱它的時(shí)候, 這個(gè)訂閱者會(huì)立即收到 BehaviorSubject 上一個(gè)發(fā)出的 event, 之后就是正常流程
    BehaviorSubject.png

(2) 使用示例

override func viewDidLoad() {
        super.viewDidLoad()
        let disposeBag = DisposeBag()
        let subject = BehaviorSubject(value: "111")
        //第一次訂閱subject(先發(fā)出上一個(gè)event)
        subject.subscribe { (event) in
            print("第一次訂閱: ", event)
        }.disposed(by: disposeBag)
        //發(fā)送next事件
        subject.onNext("222")
        subject.onError(NSError(domain: "local", code: 0, userInfo: nil))
        //重復(fù)結(jié)束event,輸出error
        subject.subscribe { (event) in
            print("第二次訂閱: ",event)
        }.disposed(by: disposeBag)
    }
    
//輸出結(jié)果
第一次訂閱:  next(111)
第一次訂閱:  next(222)
第一次訂閱:  error(Error Domain=local Code=0 "(null)")
第二次訂閱:  error(Error Domain=local Code=0 "(null)")
ReplaySubject

(1) 基本介紹

  • ReplaySubject 在創(chuàng)建的時(shí)候需要設(shè)置一個(gè) bufferSize, 表示它發(fā)送過的 event 緩存?zhèn)€數(shù). 比如 : 一個(gè) ReplaySubjectbufferSize 設(shè)置為 2, 它發(fā)出了三個(gè) .nextevent, 那么這個(gè) subscriber 就會(huì)立即收到前面緩存的兩個(gè) .nextevent

(2) 時(shí)序圖

  • ReplaySubjectbufferSize2
  • 下面兩條訂閱, 訂閱時(shí)間點(diǎn)不同. ReplaySubject 的訂閱者一開始就能受到 ReplaySubject 之前發(fā)出的兩個(gè) Event(如果有的話).
    ReplaySubject.png

    (3)案例
override func viewDidLoad() {
        super.viewDidLoad()
        let disposeBag = DisposeBag()
        let subject = ReplaySubject<String>.create(bufferSize: 2);
        //連續(xù)發(fā)出三個(gè)event
        subject.onNext("1")
        subject.onNext("2")
        subject.onNext("3")
        //第一次訂閱
        subject.subscribe { (event) in
            print("第一次訂閱", event)
        }.disposed(by: disposeBag)
        
        subject.onNext("4")
        subject.subscribe { (event) in
            print("第二次訂閱", event)
        }
        
        subject.onCompleted();
        subject.subscribe { (event) in
            print("第三次訂閱", event)
        }.disposed(by: disposeBag)
        
    }
    
//輸出結(jié)果
第一次訂閱 next(2)
第一次訂閱 next(3)
第一次訂閱 next(4)
第二次訂閱 next(3)
第二次訂閱 next(4)
第一次訂閱 completed
第二次訂閱 completed
第三次訂閱 next(3)
第三次訂閱 next(4)
第三次訂閱 completed
BehaviorRelay

(1) 基本介紹

  • BehaviorRelay 是作為 Variable 的替代者出現(xiàn)的. 它的本質(zhì)其實(shí)也是對(duì) BehaviorRelay 的封裝, 所以它也必須要通過一個(gè)默認(rèn)的初始值進(jìn)行創(chuàng)建
  • BehaviorReplay 具有 BehaviorSubject 的功能, 能夠向它的訂閱者發(fā)出上一個(gè) event 以及之后新創(chuàng)建的 event
  • BehaviorSubject 不同的是,不需要也不能手動(dòng)給 BehaviorReply 發(fā)送 completed 或者 error 事件來結(jié)束它(BehaviorRelay 會(huì)在銷毀時(shí)自動(dòng)發(fā)送 .complete 的 event)。
  • BehaviorReplay 有一個(gè) value 屬性, 我們通過這個(gè)屬性可以獲取最新值. 而通過它的 accept() 方法可以對(duì)值進(jìn)行修改.

(2) 案例

override func viewDidLoad() {
        super.viewDidLoad()
        let disposeBag = DisposeBag()
        let subject = BehaviorRelay<String>(value: "111");
        // 修改value值
        subject.accept("222");
        //第一次訂閱
        subject.subscribe { (event) in
            print("第一次訂閱: ", event)
        }.disposed(by: disposeBag)
        
        //修改value值
        subject.accept("333")
        subject.subscribe { (event) in
            print("第二次訂閱 :", event)
        }.disposed(by: disposeBag)

        subject.accept("444")
    }
//輸出結(jié)果
第一次訂閱:  next(222)
第一次訂閱:  next(333)
第二次訂閱 : next(333)
第一次訂閱:  next(444)
第二次訂閱 : next(444)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容