通常在使用RxSwift的时候,我们并不会直接去使用observable来创建序列,更多的时候使用的是一系列的subject,接下来介绍几个subject的的使用
常用的几种 :
- PublishSubject
- BehaviorSubject
3 .ReplaySubject
4 .AsyncSubject
5 .BehaviorRelay(Variable)
从PublishSubject 开始
func publishSubTest() {
// PublishSubject
// 1:初始化序列
let publishSub = PublishSubject<Int>() //初始化一个PublishSubject 装着Int类型的序列
// 2:发送响应序列
publishSub.onNext(1)
// 3:订阅序列
publishSub.subscribe { print("订阅到了:", $0) }
.disposed(by: disposbag)
// 再次发送响应
publishSub.onNext(2)
publishSub.onNext(3)
}
直接上代码,是不是有点奇怪。publishSub.onNext(1) 和publishSub.subscribe都是publishSub来调用,没错,还记得上一篇文章的中间序列嘛,对的,subject的这几种类型和SubscribeOn是一样的,自身拥有创建序列和订阅的能力。
来看问题,publishSub会输出什么呢?答案是只会输出 2和3 。代码的顺序执行,只有在订阅之后,发布订阅的方法发送的信号才会被接收。这样相比较observable来说,不用在创建的闭包中发发布订阅,使用起来更加的方便。
BehaviorSubject
func behaviorSubTest() {
// 1:创建序列
let behaviorSub = BehaviorSubject.init(value: 100)
// 2:发送信号
behaviorSub.onNext(2)
behaviorSub.onNext(3)
// 3:订阅序列
behaviorSub.subscribe{ print("订阅到了1:", $0) }
.disposed(by: disposbag)
// 再次发送
behaviorSub.onNext(4)
behaviorSub.onNext(5)
// 再次订阅
behaviorSub.subscribe{ print("订阅到了:", $0) }
.disposed(by: disposbag)
}
来看第二段代码,输出的是 3 4 5 5 ,是不是有点奇怪,BehaviorSubject在创建的时候会保存一个初始值100,途径onNext(2)的时候,2替换了100,在3的时候又替换了2,所以在第一次订阅的时候,会直接输出3,再向下,4替换3,第一次订阅收到4,第一次订阅收到5,第二次订阅收到5。
这里的原理是在创建的时候保存了一个初始值,然后在onNext的时候替换掉上一次保存的值。在订阅的时候直接发布一次订阅。自动的发布订阅原理,在上一篇timer的时候有讲到,其实是一样的。
步骤:
1 创建 :保存初始的一次订阅发布
2 订阅 :直接发布保存的订阅
ReplaySubject
func replaySubSubTest() {
// 1:创建序列
let replaySub = ReplaySubject<Int>.create(bufferSize: 2)
// let replaySub = ReplaySubject<Int>.createUnbounded()
// 2:发送信号
replaySub.onNext(1)
replaySub.onNext(2)
replaySub.onNext(3)
replaySub.onNext(4)
// 3:订阅序列
replaySub.subscribe{ print("订阅到了:", $0) }
.disposed(by: disposbag)
// 再次发送
replaySub.onNext(7)
replaySub.onNext(8)
replaySub.onNext(9)
}
其实如果可以理解BehaviorSubject的原理,这里就很好理解了
步骤:
1 创建的时候保存一个长度为bufferSize的集合
2 在onNext的时候将发布订阅保存起来,当然根据先进先出原则
3 在订阅的时候循环发布保存的订阅
AsyncSubject
func asynSubSubTest() {
// 1:创建序列
let asynSub = AsyncSubject<Int>.init()
// 2:发送信号
// asynSub.onNext(1)
// asynSub.onNext(2)
// 3:订阅序列
asynSub.onCompleted()
asynSub.subscribe{ print("订阅到了:", $0) }
.disposed(by: disposbag)
// 再次发送
asynSub.onNext(3)
asynSub.onNext(4)
// asynSub.onError(NSError.init(domain: "error", code:9999, userInfo: nil))
// asynSub.onCompleted()
}
这里来看一个比较特殊的序列,AsyncSubject遇到onError的时候会直接返回,并不会输出onNext发布的订阅。查看核心方法的时候,会发现onNext的时候会判断是否发布onCompleted订阅。如果发布了onCompleted,那么就发布在onCompleted之前的最后一次订阅和onCompleted订阅,所以AsyncSubject的订阅必须要使用onCompleted方法去最终的发布。或者onError直接返回。
BehaviorRelay
func BehaviorRelayTest() {
// Variable : 5.0已经废弃(BehaviorRelay 替换)
// 1:创建序列
let variableSub = BehaviorRelay.init(value: 1)
// 2:发送信号
variableSub.accept(100)
variableSub.accept(10)
// 3:订阅信号
variableSub.asObservable().subscribe{ print("订阅到了:", $0) }
.disposed(by: disposbag)
print("打印:\(variableSub.value)")
// 再次发送
variableSub.accept(1000)
}
BehaviorRelay 也比较的特殊,print("打印:(variableSub.value)"),这一句在这里直接调用序列的value,可以获取到上一次accept的值,当然在5.0之前的Variable,也是可以获取到onNext的值,是不是更加方便,更加好用了呢。这里打印的值为 10 ,10 ,1000,其中第二个10为variableSub.value直接获取到的。
but,桥的麻袋,这样的使用方法就违背了RxSwift的核心思想:函数响应式。
这样的使用方法更接近于面向对象的使用方法,所以不推荐使用。
写在最后:
这里只是简单的介绍了几种subject的使用,其背后的原理并没有进行详细的介绍。这几种subject使用起来比observable更加方便好用。但是在创建的时候,如果有看的话,可以看到这几种subject是没有继承自produce的,而是在直接继承自Observable和ObserverType,所以和observable的部分流程是不一样的。而BehaviorRelay 也是和subject是不一样的,后续再另外开一篇讲一下subject背后的原理。