Subject 主要包括以下几类
-
PublishSubject
, BehaviorSubject
ReplaySubject
AsyncSubject
Variable
-
BehaviorRelay
,
通过源码可以看出,他们有共同的父类,Observable
和ObserverType
,表示他们既是序列,也是订阅者
public final class PublishSubject<Element>
: Observable<Element>
, SubjectType
, Cancelable
, ObserverType
, SynchronizedUnsubscribeType {}
public final class BehaviorSubject<Element>
: Observable<Element>
, SubjectType
, ObserverType
, SynchronizedUnsubscribeType
, Cancelable {}
public class ReplaySubject<Element>
: Observable<Element>
, SubjectType
, ObserverType
, Disposable {}
public final class AsyncSubject<Element>
: Observable<Element>
, SubjectType
, ObserverType
, SynchronizedUnsubscribeType{}
public final class Variable<Element> {
public typealias E = Element
private let _subject: BehaviorSubject<Element>
接下来介绍各自的特性和用法:
PublishSubject
- 在订阅序列之前,发送的信号,不会响应
- 在订阅序列之后,发送的信号,接收响应
//初始化一个PublishSubject ,Int类型的序列
let publishSub = PublishSubject<Int>()
// 2:发送响应序列
publishSub.onNext(1)
// 3:订阅序列
publishSub.subscribe { print("订阅到了:",$0)}
.disposed(by: disposbag)
// 再次发送响应
publishSub.onNext(2)
publishSub.onNext(3)
根据PublishSubject
的特性,publishSub.onNext(1)
不会响应,所以运行结果如下:
订阅到了: next(2)
订阅到了: next(3)
BehaviorSubject
-
BehaviorSubject
初始化有一个默认值。最终会响应observer.on(.next(self._element))
- 开始收到订阅的时候,订阅者会收到
BehaviorSubject
上一个发出的event
事件,如果此时,没有任何事件,发出初始化传入的默认值
public init(value: Element) { self._element = value}
- 收到新的
onNext()
事件,会调用
case .next(let element):
self._element = element
重新赋值self._element
,保存新的事件。
// 1:创建序列
let behaviorSub = BehaviorSubject.init(value: 100)
behaviorSub.subscribe{ print("第一次订阅到了:",$0)}
.disposed(by: disposbag)
// 2:发送信号
behaviorSub.onNext(2)
behaviorSub.onNext(3)
// 3:订阅序列
behaviorSub.subscribe{ print("第二次订阅到了:",$0)}
.disposed(by: disposbag)
// 再次发送
behaviorSub.onNext(4)
behaviorSub.onNext(5)
// 再次订阅
behaviorSub.subscribe{ print("第三次订阅到了:",$0)}
.disposed(by: disposbag)
根据BehaviorSubject
的特性,运行结果:
//当前只有一个订阅者
第一次订阅到了: next(100)
第一次订阅到了: next(2)
//当前有两个订阅者
第一次订阅到了: next(3)
第二次订阅到了: next(3)
第一次订阅到了: next(4)
第二次订阅到了: next(4)
//当前有三个订阅者,依次打印
第一次订阅到了: next(5)
第二次订阅到了: next(5)
第三次订阅到了: next(5)
ReplaySubject
- 不关心是否已经有订阅者,默认发送所有事件
- 初始化一个最大缓存数
bufferSize
,保存订阅前最后发送的bufferSize
个事件,收到订阅,开始响应; - 订阅后,常规操作,有新事件发送就开始响应,接下来看
demo
// 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)
lldb
调试分析,第一个订阅者响应订阅前,保存的两次事件,值分别为3
和4
运行结果:
//响应订阅前保存的两个事件
订阅到了: next(3)
订阅到了: next(4)
//订阅后,响应所有
订阅到了: next(7)
订阅到了: next(8)
订阅到了: next(9)
AsyncSubject
- 在收到完成信号之前无论发出多少事件,只响应收到
onCompleted()
信号前,最后发送的一个事件
接下来看demo
// 1:创建序列
let asynSub = AsyncSubject<Int>.init()
// 2:发送信号
asynSub.onNext(1)
asynSub.onNext(2)
// 3:订阅序列
asynSub.subscribe{ print("订阅到了:",$0)}
.disposed(by: disposbag)
// 再次发送
asynSub.onNext(3)
asynSub.onNext(4)
//asynSub.onError(NSError.init(domain: "errorInfo", code: 111111, userInfo: nil))
asynSub.onCompleted()
lldb
调试,断点进入了在收到完成信号时,响应了最后一个保存的.onNext()
事件
运行结果如下
订阅到了: next(4)
订阅到了: completed
BehaviorRelay
- 替代
Variable
- 由于封装了
BehaviorSubject
,所以具有BehaviorSubject
的特性:a.通过一个默认值初始化;b.保存订阅信号前的最后一个事件,进行响应 - 没有
onComplete()
和onError()
功能
运行demo
如下
//1:创建序列
let behaviorSubject = BehaviorRelay(value: 11111)
//2:订阅信号
behaviorSubject.subscribe(onNext: { (num) in
print("订阅到了数值:\(num)")
}).disposed(by: disposbag)
//3:发送信号
behaviorSubject.accept(22222)
运行结果
订阅到了数值:11111
订阅到了数值:22222
以上就是subject的特性和用法;
网友评论