RxSwift之subject

通常在使用RxSwift的时候,我们并不会直接去使用observable来创建序列,更多的时候使用的是一系列的subject,接下来介绍几个subject的的使用
常用的几种 :

  1. PublishSubject
  2. 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背后的原理。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容