RxSwift(六) - Subjects、 Variables

Subjects

创建 Observable 序列之后, 要预先将要发出的数据准备好, 等到有人订阅时, 再将数据通过 Event 发出去.

我们希望 Observable 序列能在运行时动态的 获得 或者说 产生 一个新数据, 再通过 Event 发送出去. 比如: 订阅一个输入框的输入内容, 当用户每输入一个字后, 这个输入框关联的 Observable 就会发出一个带有输入内容的 Event, 通知给所有的订阅者. 这个就可以使用 Subjects 来实现.

Subjects 基本介绍

(1) Subjects 它是订阅者, 也是 Obervable :

  • 它是订阅者, 因为它能够动态的接收新的值
  • 它是一个 Observable, 是因为当 Subjects 有了新的值之后, 就会通过 Event 将新值发出给他的所有订阅者.

(2) 一共有四种 Subjects, 分别是 PublishSubjectBehaviorSubjectReplaySubjectVariable(已废弃)BehaviorRelay(Variable替代品).

  • 它们都是 Observable, 它们的订阅者都能收到它们发出的 Event
  • 直到 Subject 发出 .complete 或者 .errorEvent 之后, 该 Subject 才会终结, 不再发出 .next 事件.
  • 对于那些在 Subject 终结后再订阅的订阅者, 也能收到一条 .complete 或者 .errorEvent, 告诉这个新订阅者, 该 Subject 已经终结
  • 它们的区别在于 : 当一个新的订阅者刚订阅它的时候,能不能收到 Subject 以前发出的旧 Event, 如果能,又可以收到多少个 Event.

(3) Subject 的常用方法

  • onNext() : on(.next):的简写, 该方法相当于 subject 接收到一个 .next 事件.
  • onError() : on(.error): 的简写, 该方法相当于 subject 接收到一个 .error 事件.
  • onCompleted() : on(.completed): 的简写, 该方法相当于 subjet 接收到一个 .completed 事件
PublishSubject

(1) 基本介绍

  • PublishSubject 是最普通的 Subjet, 它不需要初始值就能创建.
  • PublishSubject 的订阅者从开始订阅的时间点起,可以收到订阅 Subject 发出的新的 Event, 而不会收到他们在订阅前已发出的 Event.
PublishSubject.png

(2)案例

override func viewDidLoad() {
        super.viewDidLoad()
        let disposeBag = DisposeBag()
        //创建一个PublishSubject
        let subject = PublishSubject()
        subject.onNext("11") //此时没有订阅者,不会输出
        
        //首次订阅
        subject.subscribe(onNext: { str in
            print("第一次订阅: ", str)
        }, onCompleted: {
            print("第一次订阅 : onCompleted")
        }).disposed(by: disposeBag)
        //有订阅者,会输出
        subject.onNext("22")
        
        subject.subscribe(onNext: { (str) in
            print("第二次订阅: ", str)
        }, onCompleted: {
            print("第二次订阅 : onCompleted")
        }).disposed(by: disposeBag)
        subject.onNext("33")//两个订阅者,输出两遍
        subject.onCompleted()//结束两个订阅者,打印两遍
        subject.onNext("44")//再次发送event,不会打印
        //再有新的订阅者,会收到onCompleted消息,通知新的订阅者,该Subject已经终结
        subject.subscribe(onNext: { (str) in
            print("第三次订阅: ", str)
        }, onCompleted: {
            print("第三次订阅 : onCompleted")
        }).disposed(by: disposeBag)
}

//输出结果 
第一次订阅:  22
第一次订阅:  33
第二次订阅:  33
第一次订阅 : onCompleted
第二次订阅 : onCompleted
第三次订阅 : onCompleted
BehaviorSubject

(1) 基本介绍

  • BehaviorSubject 需要通过一个默认初始值来创建
  • 当一个订阅者来订阅它的时候, 这个订阅者会立即收到 BehaviorSubject 上一个发出的 event, 之后就是正常流程
    BehaviorSubject.png

(2) 使用示例

override func viewDidLoad() {
        super.viewDidLoad()
        let disposeBag = DisposeBag()
        let subject = BehaviorSubject(value: "111")
        //第一次订阅subject(先发出上一个event)
        subject.subscribe { (event) in
            print("第一次订阅: ", event)
        }.disposed(by: disposeBag)
        //发送next事件
        subject.onNext("222")
        subject.onError(NSError(domain: "local", code: 0, userInfo: nil))
        //重复结束event,输出error
        subject.subscribe { (event) in
            print("第二次订阅: ",event)
        }.disposed(by: disposeBag)
    }
    
//输出结果
第一次订阅:  next(111)
第一次订阅:  next(222)
第一次订阅:  error(Error Domain=local Code=0 "(null)")
第二次订阅:  error(Error Domain=local Code=0 "(null)")
ReplaySubject

(1) 基本介绍

  • ReplaySubject 在创建的时候需要设置一个 bufferSize, 表示它发送过的 event 缓存个数. 比如 : 一个 ReplaySubjectbufferSize 设置为 2, 它发出了三个 .nextevent, 那么这个 subscriber 就会立即收到前面缓存的两个 .nextevent

(2) 时序图

  • ReplaySubjectbufferSize2
  • 下面两条订阅, 订阅时间点不同. ReplaySubject 的订阅者一开始就能受到 ReplaySubject 之前发出的两个 Event(如果有的话).
    ReplaySubject.png

    (3)案例
override func viewDidLoad() {
        super.viewDidLoad()
        let disposeBag = DisposeBag()
        let subject = ReplaySubject.create(bufferSize: 2);
        //连续发出三个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)
        
    }
    
//输出结果
第一次订阅 next(2)
第一次订阅 next(3)
第一次订阅 next(4)
第二次订阅 next(3)
第二次订阅 next(4)
第一次订阅 completed
第二次订阅 completed
第三次订阅 next(3)
第三次订阅 next(4)
第三次订阅 completed
BehaviorRelay

(1) 基本介绍

  • BehaviorRelay 是作为 Variable 的替代者出现的. 它的本质其实也是对 BehaviorRelay 的封装, 所以它也必须要通过一个默认的初始值进行创建
  • BehaviorReplay 具有 BehaviorSubject 的功能, 能够向它的订阅者发出上一个 event 以及之后新创建的 event
  • BehaviorSubject 不同的是,不需要也不能手动给 BehaviorReply 发送 completed 或者 error 事件来结束它(BehaviorRelay 会在销毁时自动发送 .complete 的 event)。
  • BehaviorReplay 有一个 value 属性, 我们通过这个属性可以获取最新值. 而通过它的 accept() 方法可以对值进行修改.

(2) 案例

override func viewDidLoad() {
        super.viewDidLoad()
        let disposeBag = DisposeBag()
        let subject = BehaviorRelay(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")
    }
//输出结果
第一次订阅:  next(222)
第一次订阅:  next(333)
第二次订阅 : next(333)
第一次订阅:  next(444)
第二次订阅 : next(444)

你可能感兴趣的:(RxSwift(六) - Subjects、 Variables)