RxSwift 系列(二) -- Subject


前言

Subject是一個代理,它既是Observer,也是Observable。因為它是一個Observer,它可以訂閱一個或多個Observable;因為它是一個Observable,它又可以被其他的Observer訂閱。它可以傳遞/轉發作為Observer收到的值,也可以主動發射值。

SubjectRxSwift中的實現有四種:

  • PublishSubject
  • ReplaySubject
  • BehaviorSubject
  • Variable

PublishSubject

代理
我們先以PublishSubject為例來解釋Subject是一個代理的含義。

let subject = PublishSubject<Int>()
subject.subscribe({ (event) in
    print("Event:\(event)")
})
    
subject.onNext(1)
subject.onNext(2)
subject.onCompleted()

Subject作為一個Observable提供了subscribe等方法。在訂閱之后,我們調用了onNext(),向Observer發射了12,以及onCompleted()。打印結果和我們預期的是一樣的。

Event:next(1)
Event:next(2)
Event:completed

我們可以調用Subjecton系列方法主動給Observer發送值。

Subject可以作為代理轉發訂閱到的結果。例如:

let subject = PublishSubject<Int>()
subject.subscribe({ (event) in
    print("Event:\(event)")
})
    
let reveseSubject = Observable<Int>.create({ (observer) -> Disposable in
    observer.onNext(1)
    observer.onNext(2)
    observer.onCompleted()
        
    return Disposables.create()
})
    
reveseSubject.subscribe(subject)

subject訂閱了reveseSubject,並將結果轉發給了Observer

注意:Observer訂閱 subject時不會收到訂閱之前subject的值。

let subject = PublishSubject<Int>()
subject.onNext(0)
subject.subscribe({ (event) in
    print("Event:\(event)")
})
    
subject.onNext(1)
subject.onNext(2)
subject.onCompleted()

上述代碼結果為:

Event:next(1)
Event:next(2)
Event:completed

observer無法接收到0這個值。

ReplaySubject

ReplaySubjectPublishSubject不同的是,Observer有可能接收到訂閱之前的值。

let subject = ReplaySubject<Int>.create(bufferSize: 1)
    
    subject.onNext(0)
    subject.subscribe({ (event) in
        print("Event:\(event)")
    })
    
    subject.onNext(1)
    subject.onNext(2)
    subject.onCompleted()

上述代碼結果為:

Event:next(0)
Event:next(1)
Event:next(2)
Event:completed

ReplaySubject具有重放(replay)的功能,replay的個數可以通過參數指定。我們可以將其理解為緩存的效果。

一般我們使用ReplaySubject的時候,都是先發射,后訂閱,然后通過指定緩存的大小,可以獲取對應的值。(注意:不考慮Error和Completed)。

let subject = ReplaySubject<Int>.create(bufferSize: 1)
    
subject.onNext(0)
subject.onNext(1)
subject.onNext(2)
subject.onCompleted()
    
subject.subscribe({ (event) in
    print("Event:\(event)")
})

上述代碼,我們指定了bufferSize等於1,所以只緩存了最新的值,打印結果:

Event:next(2)
Event:completed

當我們需要緩存所有值的時候,可以調用createUnbounded()方法。

ReplaySubject .create(bufferSize: 0) 等同於 PublishSubject ()。

BehaviorSubject

BehaviorSubject類似於ReplaySubject具有緩存能力,但是略有不同。

  • 只緩存一個最新值,類似ReplaySubject.create(bufferSize: 1)
  • 需要提供默認值
let behaviorSubject = BehaviorSubject<Int>(value: 1)
behaviorSubject.subscribe({ (event) in
    print("Event:\(event)")
})

打印結果為:

Event:next(1)

使用BehaviorSubject有一點好處,我們可以確定當Observer訂閱時,至少可以收到最新的一個值。

Variable

VariableBehaviorSubject又很相似,VariableBehaviorSubject的一個封裝,同樣具備了緩存最新值和提供默認值的能力。但是Variable沒有on系列方法,只提供了value屬性。
直接對value進行set等同於調用了onNext()方法。

這表明了Variable不會發射error也不會發射completed

Variable被銷毀的時候會調用發射completedObserver

在訂閱Variable的時候,我們無法直接調用subscribe方法,需要先調用asObservable()方法。

let variable = Variable<Int>(1)
variable.asObservable().subscribe({ (event) in
    print("Event:\(event)")
})
variable.value = 2

上述結果為:

Event:next(1)
Event:next(2)
Event:completed

Variable可以用來儲存數據,因為我們可以擁有valuegetset方法。比如:

let variable = Variable(1)
print("Value: \(variable.value)")
variable.value = 2
print("Value: \(variable.value)")

打印結果為:

Value: 1
Value: 2

這是BehaviorSubject不具備的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM