RxSwift的subjects记录(二)

2019-04-11  本文已影响0人  timeQuick

Subject

英文文档中subject的定义:
Observables are a fundamental part of RxSwift, but a common need when developing apps is to manually add new values onto an observable at runtime that will then be emitted to subscribers. What you want is something that can act as both an observable and as an observer. And that something is called a Subject.个人理解subject是具有observable特性(创建,订阅,取消)又有observer特性(可以动态的产生新的事件Event)的东西

There are four subject types in RxSwift:
• PublishSubject: Starts empty and only emits new elements to subscribers.(无需初使化,只发送最新的值给订阅者)
• BehaviorSubject: Starts with an initial value and replays it or the latest element to new subscribers.(有初使化值,能给新的订阅者最新的发送过的值)
• ReplaySubject: Initialized with a buffer size and will maintain a buffer of elements up to that size and replay it to new subscribers.(需使用buffer size初使化,能给新的订阅者buffe size里的所有值)
• Variable: Wraps a BehaviorSubject, preserves its current value as state, and replays only the latest/initial value to new subscribers.

PublishSubject

 func testPublishSubject()
    {
        let subject = PublishSubject<String>()  //string代表要传的值类型
        
        subject.onNext("111")  //这里不会输出,因为还没有订阅。
        //第一次订阅
       let sub1 =  subject.subscribe(onNext: { (string) in
            print("第1次订阅:\(string)")
        }, onError: { (err) in
             print("第1次订阅Err:\(err)")
        }, onCompleted: {
             print("第1次订阅:onCompleted)")
        })
        subject.onNext("222"); //因为订阅了所以,可以收到。
        
        //第二次订阅
        let sub2 =  subject.subscribe(onNext: { (string) in
            print("第2次订阅:\(string)")
        }, onError: { (err) in
            print("第2次订阅Err:\(err)")
        }, onCompleted: {
            print("第2次订阅:onCompleted)")
        })
        subject.onNext("333") //2次订阅都能收到
        subject.onCompleted() //subject已经结束 ,后面的发送都不会收到了。
  
        subject.onNext("444") //subject已经结束 不会收到。
        let disposeBag = DisposeBag()
        //第三次订阅 subject完成后它后面的订阅都只能收到subject的.completed事件
        let sub3 =  subject.subscribe(onNext: { (string) in
            print("第3次订阅:\(string)")
        }, onError: { (err) in
            print("第3次订阅Err:\(err)")
        }, onCompleted: {
            print("第3次订阅:onCompleted)")
        }) .disposed(by: disposeBag)
       
        subject.onNext("?")
        //第四次订阅  subject完成后它后面的订阅都只能收到subject的.completed事件
        let sub4 =  subject.subscribe(onNext: { (string) in
            print("第4次订阅:\(string)")
        }, onError: { (err) in
            print("第4次订阅Err:\(err)")
        }, onCompleted: {
            print("第4次订阅:onCompleted)")
        })
    }
> 输出
第1次订阅:222
第1次订阅:333
第2次订阅:333
第1次订阅:onCompleted)
第2次订阅:onCompleted)
第3次订阅:onCompleted)

在写了subject.onCompleted()后,后面的订阅就只能收到它的onCompleted事件了,为什么这样设计?原文的回答。Actually, every subject type, once terminated, will re-emit its stop event to future subscribers. So it’s a good idea to include handlers for stop events in your code, not just to be notified when it terminates, but also in case it is already terminated when you subscribe to it.是为了方便stop时自己处理场景。

问题:如果我想后面我的订阅 subject.subscribe能返回我之前订阅收到的最新那个元素就好了?
于是新的类型的设计BehaviorSubjects出来了.

BehaviorSubjects

这个类型与PublishSubject有什么区别,我想它的一个Note很好的说明了。

Note: Since BehaviorSubject always emits the latest element, you can't create one without providing a default initial value. If you can't provide a default initial value at creation time, that probably means you need to use a PublishSubject instead.

重点的不同是在创建的时候有一个初使值及获得最新的值。

  func testBehaviorSubject()  {
        
        //创建一个BehaviorSubject
        let subject = BehaviorSubject(value: "Initial value")
        let disposeBag = DisposeBag()
        
         subject.onNext("111")
        //第1次订阅subject
        let sub1 =  subject.subscribe(onNext: { (string) in
            print("第1次订阅:\(string)")
        }, onError: { (err) in
            print("第1次订阅Err:\(err)")
        }, onCompleted: {
            print("第1次订阅:onCompleted)")
        })
        
        //发送next事件
        subject.onNext("222")
        
        //发送error事件  把这句放开,后面的订阅就收不到了。因为.error事件 代表subject结束完成了。
//        subject.onError(NSError(domain: "local", code: 0, userInfo: nil))
        
        //第二次订阅
        print("=========第2次开始订阅============")
        let sub2 =  subject.subscribe(onNext: { (string) in
            print("第2次订阅:\(string)")
        }, onError: { (err) in
            print("第2次订阅Err:\(err)")
        }, onCompleted: {
            print("第2次订阅:onCompleted)")
        })
        subject.onNext("333")
        //第三次订阅
        print("=========第3次开始订阅============")
        let sub3 =  subject.subscribe(onNext: { (string) in
            print("第3次订阅:\(string)")
        }, onError: { (err) in
            print("第3次订阅Err:\(err)")
        }, onCompleted: {
            print("第3次订阅:onCompleted)")
        }) .disposed(by: disposeBag)
    
        subject.onNext("444")
    }
输出:
第1次订阅:111
第1次订阅:222
=========第2次开始订阅============
第2次订阅:222
第1次订阅:333
第2次订阅:333
=========第3次开始订阅============
第3次订阅:333
第1次订阅:444
第2次订阅:444
第3次订阅:444

在没有第1次订阅时,subject.onNext("111"),111把初使值替换了。后面的每一次订阅都会输出历史收到的最新的值。
问题:如果我要后面的订阅返回更多的历史值呢?
所以ReplaySubject出现了。

ReplaySubject

根据bufferSize的设置可以返回订阅之前发送的历史值

  func testReplaySubject()
    {
       //创建一个bufferSize为2的ReplaySubject
        let subject = ReplaySubject<String>.create(bufferSize: 2)
        let disposeBag = DisposeBag()
    
        subject.onNext("111")
        subject.onNext("222")
        subject.onNext("333")
        
        //第1次订阅subject
        let sub1 =  subject.subscribe(onNext: { (string) in
            print("第1次订阅:\(string)")
        }, onError: { (err) in
            print("第1次订阅Err:\(err)")
        }, onCompleted: {
            print("第1次订阅:onCompleted)")
        })
        subject.onNext("444")
        //第二次订阅
        print("=========第2次开始订阅============")
        let sub2 =  subject.subscribe(onNext: { (string) in
            print("第2次订阅:\(string)")
        }, onError: { (err) in
            print("第2次订阅Err:\(err)")
        }, onCompleted: {
            print("第2次订阅:onCompleted)")
        })
        subject.onNext("333")
        
    }
输出:
第1次订阅:222
第1次订阅:333
第1次订阅:444
=========第2次开始订阅============
第2次订阅:333
第2次订阅:444
第1次订阅:333
第2次订阅:333

后面的订阅能够接收到之前发送的值。

最后

上一篇 下一篇

猜你喜欢

热点阅读