美文网首页iOS第三方库
RxSwift(六)-- RxSwift使用介绍Subject

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

作者: Daniel_Harvey | 来源:发表于2019-08-04 11:15 被阅读0次

    Subject介绍

    从之前的文章RxSwift(三)-- RxSwift使用介绍Observable的创建中,我们可以知道,当我们需要创建一个 Observable的时候,要预先将要发出的数据都准备好,等到有人订阅它时再将数据通过 Event发出去。
    不过,有时我们也希望 Observable 在运行时能动态地“获得”或者说“产生”出一个新的数据,再通过 Event 发送出去。比如:订阅一个输入框的输入内容,当用户每输入一个字后,这个输入框关联的 Observable 就会发出一个带有输入内容的 Event,通知给所有订阅者。
    这个时候,我们要介绍的Subject就登场了。

    Subject基本介绍

    1. Subject它既是订阅者,也是Observable序列:
    • 因为它能够动态地接收新的值,所以它是订阅者。
    • 因为Subject有了新的值以后,会通过Event事件将新的值发出来给到订阅者,所以它又是一个Observable序列。
    1. RxSwiftSubject的分类是:PublishSubjectBehaviorSubjectReplaySubjectAsyncSubjectBehaviorRelay,它们之间既有各自的特点,也有相同之处:
    • 它们都是Observable序列,订阅者都能收到它们发出的新的Event
    • 等到Subject发出.complete或者.errorEventSubject也就结束了,也就不会再发出.next事件了。
    • 如果在Subject结束后再订阅的订阅者,也可以收到Subject发出的一条.complete或者.error事件,用来告诉订阅者已经结束了。
    • 它们之间的最大区别是:当一个新的订阅者刚订阅它的时候,能不能收到 Subject 以前发出过的旧 Event,如果能的话又能收到多少个。
    1. Subject的常用方法:
    • onNext(:):是 on(.next(:)) 的简便写法。该方法相当于 Subject 接收到一个 .next 事件。
    • onError(:):是 on(.error(:)) 的简便写法。该方法相当于 Subject 接收到一个 .error 事件。
    • onCompleted():是 on(.completed) 的简便写法。该方法相当于 subject 接收到一个 .completed 事件。

    PublishSubject

    1. 介绍
    • PublishSubject不需要初始值就能创建(也就是可以为空)。
    • PublishSubject的订阅者从他们开始订阅的时间点起,可以收到订阅后 Subject 发出的新 Event事件,而不会收到他们在订阅前已发出的 Event事件。
    1. 代码展示
    // 创建一个PublishSubject
            let subject = PublishSubject<String>()
            
            // 由于当前没有任何订阅者,所以这条信息不会输出到控制台
            subject.onNext("111")
            
            // 第1次订阅subject
            subject.subscribe(onNext: { string in
                print("第1次订阅:", string)
            }, onCompleted:{
                print("第1次订阅:onCompleted")
            }).disposed(by: disposeBag)
            
            // 当前有1个订阅,则该信息会输出到控制台
            subject.onNext("222")
           
            // 第2次订阅subject
            subject.subscribe(onNext: { string in
                print("第2次订阅:", string)
            }, onCompleted:{
                print("第2次订阅:onCompleted")
            }).disposed(by: disposeBag)
            
            // 当前有2个订阅,则该信息会输出到控制台
            subject.onNext("333")
            
            // 让subject结束
            subject.onCompleted()
            
            // subject完成后会发出.next事件了。
            subject.onNext("444")
            // subject完成后它的所有订阅(包括结束后的订阅),都能收到subject的.completed事件,
            subject.subscribe(onNext: { string in
                print("第3次订阅:", string)
            }, onCompleted:{
                print("第3次订阅:onCompleted")
            }).disposed(by: disposeBag)
    

    运行结果:

    第1次订阅: 222
    第1次订阅: 333
    第2次订阅: 333
    第1次订阅:onCompleted
    第2次订阅:onCompleted
    第3次订阅:onCompleted
    

    BehaviorSubject

    1. 介绍
    • BehaviorSubject 需要通过一个默认初始值来创建。
    • 当一个订阅者来订阅它的时候,这个订阅者会立即收到 BehaviorSubjects 上一个发出的 event事件,如果还没有收到任何数据,则会发出一个默认值。之后就跟PublishSubject正常的情况一样,它也会接收到 BehaviorSubject 之后发出的新的 event事件。
    1. 代码展示
    // 创建一个BehaviorSubject
            let subject = BehaviorSubject(value: "111")
            
            // 第1次订阅subject
            subject.subscribe { event in
                print("第1次订阅:", event)
                }.disposed(by: disposeBag)
            
            // 发送next事件
            subject.onNext("222")
            
            // 发送error事件
            subject.onError(NSError(domain: "local", code: 0, userInfo: nil))
            
            // 第2次订阅subject
            subject.subscribe { event in
                print("第2次订阅:", event)
                }.disposed(by: disposeBag)
    

    运行结果:

    第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 在创建时候需要设置一个 bufferSize,表示它对于它发送过的 event 的缓存个数。
    • 比如一个 ReplaySubjectbufferSize 设置为 2,它发出了 3 个 .nextevent,那么它会将后两个(最近的两个)event 给缓存起来。此时如果有一个 subscriber 订阅了这个 ReplaySubject,那么这个 subscriber 就会立即收到前面缓存的两个 .nextevent
    • 如果一个 subscriber 订阅已经结束的 ReplaySubject,除了会收到缓存的 .nextevent 外,还会收到那个终结的 .error 或者 .completeevent
    1. 代码展示
    //创建一个bufferSize为2的ReplaySubject
            let subject = ReplaySubject<String>.create(bufferSize: 2)
            
            //连续发送3个next事件
            subject.onNext("111")
            subject.onNext("222")
            subject.onNext("333")
            
            //第1次订阅subject
            subject.subscribe { event in
                print("第1次订阅:", event)
                }.disposed(by: disposeBag)
            
            //再发送1个next事件
            subject.onNext("444")
            
            //第2次订阅subject
            subject.subscribe { event in
                print("第2次订阅:", event)
                }.disposed(by: disposeBag)
            
            //让subject结束
            subject.onCompleted()
            
            //第3次订阅subject
            subject.subscribe { event in
                print("第3次订阅:", event)
                }.disposed(by: disposeBag)
    

    运行结果:

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

    运行结果:

    第1次订阅: next(222)
    第1次订阅: next(333)
    第2次订阅: next(333)
    第1次订阅: next(444)
    第2次订阅: next(444)
    
    1. 另外,如果想将新值合并到原值上,可以通过 accept() 方法与 value 属性配合来实现。(这个常用在表格上拉加载功能上,BehaviorRelay 用来保存所有加载到的数据)
    //创建一个初始值为包含一个元素的数组的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"])
    

    运行结果:

    第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完成后,发射来自原始Observable的最后一个值。
    • 如果原始Observable没有发射任何值,AsyncObject也不发射任何值,它会把这最后一个值发射给任何后续的观察者。
    • 如果原始的Observable因为发生了错误而终止,AsyncSubject将不会发射任何数据,只是简单的向前传递这个错误通知。
    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)
    

    运行结果:

    observerA: 3
    observerB: 3
    observerC: 3
    observerA: onCompleted
    observerB: onCompleted
    observerC: onCompleted
    observerD: 3
    observerD: onCompleted
    

    相关文章

      网友评论

        本文标题:RxSwift(六)-- RxSwift使用介绍Subject

        本文链接:https://www.haomeiwen.com/subject/qgbpdctx.html