RxSwift学习-12-Subject的使用(上)

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

本文主要介绍subject的子类PublishSubjectBehaviorSubject使用和简单的原理。

1. SubjectType

对于我们的序列,通常创建的时候在subscriberHandle闭包中调用观察者observsronNext发送事件。比如:

//1.创建

        let ob = Observable<Any>.create{ (obserber) -> Disposable in

            

            //3.发送信号

            obserber.onNext("hello")

            obserber.onError(NSError.init(domain: "NetWorkError", code: 400, userInfo: nil))

            //obserber.onCompleted()

            return Disposables.create()

            

        }

        //2.订阅

        

        ob.subscribe(onNext: { (value) in

            

            print(value)

            

        }, onError:{ (error) in

            

            print(error)

            

        } , onCompleted: {

            

            print("订阅完成")

        }, onDisposed: {

            print("订阅销毁")

        }).disposed(by: disposeBag)

复制代码

很麻烦,我们希望我们可观察序列既可以具有观察者的发送事件on,也可以subscribe订阅。因此SubjectType就应运而生

image.png

协议SubjectType遵循了ObservableType协议,因此可以subscribe,同时关联类型遵循ObserverType协议,因此具备了发送事件on的能力。我们定义的类遵循该协议就具备了订阅和发送事件的能力。下面介绍下遵循该协议的类如何使用

2. PublishSubject

先看下使用

/// 订阅subscribe后才会生效

    func publishSubjectMethod() {

        

        let publishSubject = PublishSubject<Int>()

        publishSubject.onNext(1)

        publishSubject.onNext(2)//没有保存值

        publishSubject.subscribe(onNext: {print("publishSubject第一次订阅",$0)})

            .disposed(by: disposeBag)

        publishSubject.onNext(3)

        

        publishSubject.subscribe(onNext: {print("publishSubject再次订阅",$0)})

            .disposed(by: disposeBag)

        publishSubject.onNext(4)

    }
复制代码

打印结果

image.png

可以发现我们之前发送的事件没有保存,只有订阅后发送的事件才进行了回调。

1.1 初始化

查看下原理

image.png

首先它遵循了我们之前看的SubjectType协议因此具备了订阅和发送的事件的能力。其次保存了我们订阅者Observers,让它具备了状态的保存。这里举个例子

image.png 对于普通序列,订阅的时候会调用订阅闭包。但是我们其实只需要一次,通常我们可以使用share共享

image.png

我们使用publishconnect

image.png

也是同样的效果,都是一次发送多个订阅

2.2 订阅

image.png 对我们的数据处理进行加锁处理

image.png

关键字defer 表示return后调用,进行解锁。我们日常开发的时候也可以这样使用。
闭包调用会synchronized_subscribe方法并传入我们外部的eventHanlde闭包。首先判断闭包的状态,我们不用太关注。

我们关注下画框的关键地方 ,这里我们observers是一个数组插入我们订阅的回调事件eventHandlobserver.on

  • SubscriptionDisposable

我们看下这里保存我们key即之前的订阅事件回调数组,销毁的时候处理数组

image.png

2.2 发送

image.png

发送的时候调用dispatch(),首先会调用里面的参数即调用synchronized_on方法

image.png 该方法可以发现会返回我们订阅的时候保存的observers(eventHandle订阅的闭包)数组。对于complete和error事件则是处理清空。
我们这个时候会调用我们的dispatch(self.synchronized_on(event), event)。传入我们的事件回调数组,和事件类型。 image.png

首先调用事件数组的第一个闭包进行回调

image.png 我认为这样是为了节约时间减少一些逻辑上的处理。比我我们取数组的第一个值,没有的话就表示有问题,不用走下面的流程

image.png

因为我们开始的时候没有订阅直接发送事件,所以我们的事件回调闭包数组为空。当我们订阅的时候。进入on之后调用onCore

image.png

关于_onlyFastPath表示是否只有一个订阅者,走快速通道。

image.png

当我们有2个订阅者的时候

image.png

会获取除去第一个剩下的回调数组进行回调

- _dictionary 对于_dictionary存放的是我们最后的一个闭包回调,只有插入的时候我们回调数组大于30的时候才会存储。

image.png

3. BehaviorSubject

关于BehaviorSubject和我们的PublishSubject类似的,只是多了一个保存我们发送元素的值

  • 使用
/// 在订阅前保存一个值

    func behaviorSubjectMethod() {

        

        let behaviorSubject = BehaviorSubject<Int>.init(value: 2)

        behaviorSubject.subscribe(onNext: {print("BehaviorSubject首次订阅",$0)})

            .disposed(by: disposeBag)

        

        behaviorSubject.onNext(4)

        behaviorSubject.subscribe(onNext: {print("BehaviorSubject再次订阅",$0)})

            .disposed(by: disposeBag)

        

        behaviorSubject.onNext(5)

    

    }
复制代码

打印结果 image.png

我们简单分析下

  • 初始化

image.png

初始化的时候会保存我们的元素

  • 订阅

订阅的时候相比PublishSubject多了一步主动调用订阅eventHandle的回调

image.png

  • 发送事件

image.png 保存我们发送的元素,这样在有订阅者订阅的时候会发送最后一次发送的元素

4. 总结

主要介绍了PublishSubjectbehaviorSubject的使用,通过详细探讨Publish Subject,让我们知道了subject具备了subscribe和on的特性,从而既能订阅也能发送响应。后面介绍下余下的几种subject使用和原理。

猜你喜欢

转载自juejin.im/post/7086441803376754719