RxSwift(六)-- RxSwift使用介紹Subject

Subject介紹

從之前的文章RxSwift(三)-- RxSwift使用介紹Observable的創(chuàng)建中,我們可以知道,當(dāng)我們需要創(chuàng)建一個 Observable的時候,要預(yù)先將要發(fā)出的數(shù)據(jù)都準(zhǔn)備好,等到有人訂閱它時再將數(shù)據(jù)通過 Event發(fā)出去。
不過,有時我們也希望 Observable 在運(yùn)行時能動態(tài)地“獲得”或者說“產(chǎn)生”出一個新的數(shù)據(jù),再通過 Event 發(fā)送出去。比如:訂閱一個輸入框的輸入內(nèi)容,當(dāng)用戶每輸入一個字后,這個輸入框關(guān)聯(lián)的 Observable 就會發(fā)出一個帶有輸入內(nèi)容的 Event,通知給所有訂閱者。
這個時候,我們要介紹的Subject就登場了。

Subject基本介紹

  1. Subject它既是訂閱者,也是Observable序列:
  • 因?yàn)樗軌騽討B(tài)地接收新的值,所以它是訂閱者。
  • 因?yàn)?code>Subject有了新的值以后,會通過Event事件將新的值發(fā)出來給到訂閱者,所以它又是一個Observable序列。
  1. RxSwiftSubject的分類是:PublishSubject、BehaviorSubject、ReplaySubjectAsyncSubject、BehaviorRelay,它們之間既有各自的特點(diǎn),也有相同之處:
  • 它們都是Observable序列,訂閱者都能收到它們發(fā)出的新的Event。
  • 等到Subject發(fā)出.complete或者.errorEvent,Subject也就結(jié)束了,也就不會再發(fā)出.next事件了。
  • 如果在Subject結(jié)束后再訂閱的訂閱者,也可以收到Subject發(fā)出的一條.complete或者.error事件,用來告訴訂閱者已經(jīng)結(jié)束了。
  • 它們之間的最大區(qū)別是:當(dāng)一個新的訂閱者剛訂閱它的時候,能不能收到 Subject 以前發(fā)出過的舊 Event,如果能的話又能收到多少個。
  1. Subject的常用方法:
  • onNext(:):是 on(.next(:)) 的簡便寫法。該方法相當(dāng)于 Subject 接收到一個 .next 事件。
  • onError(:):是 on(.error(:)) 的簡便寫法。該方法相當(dāng)于 Subject 接收到一個 .error 事件。
  • onCompleted():是 on(.completed) 的簡便寫法。該方法相當(dāng)于 subject 接收到一個 .completed 事件。

PublishSubject

  1. 介紹
  • PublishSubject不需要初始值就能創(chuàng)建(也就是可以為空)。
  • PublishSubject的訂閱者從他們開始訂閱的時間點(diǎn)起,可以收到訂閱后 Subject 發(fā)出的新 Event事件,而不會收到他們在訂閱前已發(fā)出的 Event事件。
  1. 代碼展示
// 創(chuàng)建一個PublishSubject
        let subject = PublishSubject<String>()
        
        // 由于當(dāng)前沒有任何訂閱者,所以這條信息不會輸出到控制臺
        subject.onNext("111")
        
        // 第1次訂閱subject
        subject.subscribe(onNext: { string in
            print("第1次訂閱:", string)
        }, onCompleted:{
            print("第1次訂閱:onCompleted")
        }).disposed(by: disposeBag)
        
        // 當(dāng)前有1個訂閱,則該信息會輸出到控制臺
        subject.onNext("222")
       
        // 第2次訂閱subject
        subject.subscribe(onNext: { string in
            print("第2次訂閱:", string)
        }, onCompleted:{
            print("第2次訂閱:onCompleted")
        }).disposed(by: disposeBag)
        
        // 當(dāng)前有2個訂閱,則該信息會輸出到控制臺
        subject.onNext("333")
        
        // 讓subject結(jié)束
        subject.onCompleted()
        
        // subject完成后會發(fā)出.next事件了。
        subject.onNext("444")
        // subject完成后它的所有訂閱(包括結(jié)束后的訂閱),都能收到subject的.completed事件,
        subject.subscribe(onNext: { string in
            print("第3次訂閱:", string)
        }, onCompleted:{
            print("第3次訂閱:onCompleted")
        }).disposed(by: disposeBag)

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

第1次訂閱: 222
第1次訂閱: 333
第2次訂閱: 333
第1次訂閱:onCompleted
第2次訂閱:onCompleted
第3次訂閱:onCompleted

BehaviorSubject

  1. 介紹
  • BehaviorSubject 需要通過一個默認(rèn)初始值來創(chuàng)建。
  • 當(dāng)一個訂閱者來訂閱它的時候,這個訂閱者會立即收到 BehaviorSubjects 上一個發(fā)出的 event事件,如果還沒有收到任何數(shù)據(jù),則會發(fā)出一個默認(rèn)值。之后就跟PublishSubject正常的情況一樣,它也會接收到 BehaviorSubject 之后發(fā)出的新的 event事件。
  1. 代碼展示
// 創(chuàng)建一個BehaviorSubject
        let subject = BehaviorSubject(value: "111")
        
        // 第1次訂閱subject
        subject.subscribe { event in
            print("第1次訂閱:", event)
            }.disposed(by: disposeBag)
        
        // 發(fā)送next事件
        subject.onNext("222")
        
        // 發(fā)送error事件
        subject.onError(NSError(domain: "local", code: 0, userInfo: nil))
        
        // 第2次訂閱subject
        subject.subscribe { event in
            print("第2次訂閱:", event)
            }.disposed(by: disposeBag)

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

第1次訂閱: next(111)
第1次訂閱: next(222)
第1次訂閱: error(Error Domain=local Code=0 "(null)")
第2次訂閱: error(Error Domain=local Code=0 "(null)")

ReplaySubject

  1. 介紹
  • ReplaySubject 在創(chuàng)建時候需要設(shè)置一個 bufferSize,表示它對于它發(fā)送過的 event 的緩存?zhèn)€數(shù)。
  • 比如一個 ReplaySubjectbufferSize 設(shè)置為 2,它發(fā)出了 3 個 .nextevent,那么它會將后兩個(最近的兩個)event 給緩存起來。此時如果有一個 subscriber 訂閱了這個 ReplaySubject,那么這個 subscriber 就會立即收到前面緩存的兩個 .nextevent
  • 如果一個 subscriber 訂閱已經(jīng)結(jié)束的 ReplaySubject,除了會收到緩存的 .nextevent 外,還會收到那個終結(jié)的 .error 或者 .completeevent。
  1. 代碼展示
//創(chuàng)建一個bufferSize為2的ReplaySubject
        let subject = ReplaySubject<String>.create(bufferSize: 2)
        
        //連續(xù)發(fā)送3個next事件
        subject.onNext("111")
        subject.onNext("222")
        subject.onNext("333")
        
        //第1次訂閱subject
        subject.subscribe { event in
            print("第1次訂閱:", event)
            }.disposed(by: disposeBag)
        
        //再發(fā)送1個next事件
        subject.onNext("444")
        
        //第2次訂閱subject
        subject.subscribe { event in
            print("第2次訂閱:", event)
            }.disposed(by: disposeBag)
        
        //讓subject結(jié)束
        subject.onCompleted()
        
        //第3次訂閱subject
        subject.subscribe { event in
            print("第3次訂閱:", event)
            }.disposed(by: disposeBag)

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

第1次訂閱: next(222)
第1次訂閱: next(333)
第1次訂閱: next(444)
第2次訂閱: next(333)
第2次訂閱: next(444)
第1次訂閱: completed
第2次訂閱: completed
第3次訂閱: next(333)
第3次訂閱: next(444)
第3次訂閱: completed

BehaviorRelay

  1. 介紹
  • BehaviorRelay 是作為 Variable 的替代者出現(xiàn)的。它的本質(zhì)其實(shí)也是對 BehaviorSubject 的封裝,所以它也必須要通過一個默認(rèn)的初始值進(jìn)行創(chuàng)建。
  • BehaviorRelay 具有 BehaviorSubject 的功能,能夠向它的訂閱者發(fā)出上一個 event 以及之后新創(chuàng)建的 event。
  • BehaviorSubject 不同的是,不需要也不能手動給 BehaviorReply 發(fā)送 completed 或者 error 事件來結(jié)束它(BehaviorRelay 在銷毀時也不會自動發(fā)送 .completeevent)。
  • BehaviorRelay 有一個 value屬性,我們通過這個屬性可以獲取最新值。而通過它的 accept() 方法可以對值進(jìn)行修改。
  1. 代碼展示
//創(chuàng)建一個初始值為111的BehaviorRelay
        let subject = BehaviorRelay<String>(value: "111")
        
        //修改value值
        subject.accept("222")
        
        //第1次訂閱
        subject.asObservable().subscribe {
            print("第1次訂閱:", $0)
            }.disposed(by: disposeBag)
        
        //修改value值
        subject.accept("333")
        
        //第2次訂閱
        subject.asObservable().subscribe {
            print("第2次訂閱:", $0)
            }.disposed(by: disposeBag)
        
        //修改value值
        subject.accept("444")

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

第1次訂閱: next(222)
第1次訂閱: next(333)
第2次訂閱: next(333)
第1次訂閱: next(444)
第2次訂閱: next(444)
  1. 另外,如果想將新值合并到原值上,可以通過 accept() 方法與 value 屬性配合來實(shí)現(xiàn)。(這個常用在表格上拉加載功能上,BehaviorRelay 用來保存所有加載到的數(shù)據(jù))
//創(chuàng)建一個初始值為包含一個元素的數(shù)組的BehaviorRelay
        let subject = BehaviorRelay<[String]>(value: ["1"])
        
        //修改value值
        subject.accept(subject.value + ["2", "3"])
        
        //第1次訂閱
        subject.asObservable().subscribe {
            print("第1次訂閱:", $0)
            }.disposed(by: disposeBag)
        
        //修改value值
        subject.accept(subject.value + ["4", "5"])
        
        //第2次訂閱
        subject.asObservable().subscribe {
            print("第2次訂閱:", $0)
            }.disposed(by: disposeBag)
        
        //修改value值
        subject.accept(subject.value + ["6", "7"])

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

第1次訂閱: next(["1", "2", "3"])
第1次訂閱: next(["1", "2", "3", "4", "5"])
第2次訂閱: next(["1", "2", "3", "4", "5"])
第1次訂閱: next(["1", "2", "3", "4", "5", "6", "7"])
第2次訂閱: next(["1", "2", "3", "4", "5", "6", "7"])

AsyncSubject

  1. 介紹
  • 一個AsyncSubject只在原始Observable完成后,發(fā)射來自原始Observable的最后一個值。
  • 如果原始Observable沒有發(fā)射任何值,AsyncObject也不發(fā)射任何值,它會把這最后一個值發(fā)射給任何后續(xù)的觀察者。
  • 如果原始的Observable因?yàn)榘l(fā)生了錯誤而終止,AsyncSubject將不會發(fā)射任何數(shù)據(jù),只是簡單的向前傳遞這個錯誤通知。
  1. 代碼展示
let subject = AsyncSubject<Int>()
        
        subject.onNext(1)
        
        subject.subscribe(onNext: { int in
            print("observerA: \(int)")
        }, onCompleted: {
            print("observerA: onCompleted")
        }).disposed(by: disposeBag)
        
        subject.onNext(2)
        
        subject.subscribe(onNext: { int in
            print("observerB: \(int)")
        }, onCompleted: {
            print("observerB: onCompleted")
        }).disposed(by: disposeBag)
        
        subject.onNext(3)
        
        subject.subscribe(onNext: { int in
            print("observerC: \(int)")
        }, onCompleted: {
            print("observerC: onCompleted")
        }).disposed(by: disposeBag)
        
        subject.onCompleted()
        
        subject.onNext(4)
        
        subject.subscribe(onNext: { int in
            print("observerD: \(int)")
        }, onCompleted: {
            print("observerD: onCompleted")
        }).disposed(by: disposeBag)

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

observerA: 3
observerB: 3
observerC: 3
observerA: onCompleted
observerB: onCompleted
observerC: onCompleted
observerD: 3
observerD: onCompleted
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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