iOS-RXSwift

swift(4)RxSwift之share(资源共享)原理探究

2019-08-01  本文已影响191人  __拼搏__

一需求

开发中有时候会碰到一种需求:当某一个网络请求正在请求的过程中,别的地方又发起同样的一个网络请求,此时要求不再发送同样的请求,而正在发生的请求拿到数据后要返回给两个发起者,如图


image.png


二解决

RxSwift里就有这种问题的解决方式。代码如下:我们用sleep(2)模拟网络请求

 let netOB = Observable<Any>.create { (observer) -> Disposable in
            sleep(2)// 模拟网络延迟
            print("我开始请求网络了")
            observer.onNext("请求结果")
            observer.onNext("请求结果")
            observer.onCompleted()
            return Disposables.create {
                print("销毁回调了")
            }
            }
            .publish()
        
        netOB.subscribe(onNext: { (anything) in
            print("发起者1订阅到了:",anything)
        }).disposed(by: disposeBag)
        
        netOB.subscribe(onNext: { (anything) in
            print("发起者2订阅到了:",anything)
        }).disposed(by: disposeBag)
        _ = netOB.connect()

打印结果为

我开始请求网络了
发起者1订阅到了: 请求结果
发起者2订阅到了: 请求结果
发起者1订阅到了: 请求结果
发起者2订阅到了: 请求结果
销毁回调了

我们可以看到,请求只发送了一次,两个订阅者都拿到了请求结果。

三原理

这种资源共享的观察者模式,跟普通观察者模式表现上的区别仅仅在于多了个.publish()netOB.connect()

先看一下.publish()的原理,点进去

image.png
继续查看multicast

这里返回了一个ConnectableObservableAdapter类,并传入了两个参数:AnonymousObservablesubjectAnonymousObservable我们已经非常熟悉,至于subject我们先不管,只需要记住这里传了进去一个普通的subject类。具体内容我们后边再看。

我们再来看我们写的代码

image.png
此时我们能发现,这个netOB已经不再是我们熟悉的AnonymousObservable类。而是一个ConnectableObservableAdapter类。这个类持有了AnonymousObservable类(此类类通过create持有了网络请求的闭包,详见底层原理探究一篇)与一个subject类。

继续看订阅方法

image.png
这个subscribe的实现我们已经很熟悉了 image.png
这里标注的地方不再是AnonymousObservable类而是ConnectableObservableAdapter类。所以我们点进去subscribe image.png
这里的self.lazySubject就是我们的之前提到的subject类,我们继续跟进去
image.png
核心代码已经被我圈出来。这里的_observers其实是个Bag袋子。而这一步的操作是把observer.on方法,插入到袋子中,我们继续跟进这个insert操作。
image.png
可以看出,这里把observer.on方法与key做了映射。并把所有的observer闭包都存储了起来 image.png

再来看connect()方法,点进去

image.png
我们应当注意到:
①图中的核心参数,就是之前提到的subject
②图中的参数一,就是AnonymousObservable
③核心方法,其实也就是调用了producersubscribe方法。
subscribe方法,把connection作为参数传递了进去,而connection持有了subject类。而此时的subject类已经持有了我们所有的订阅。
接下来就又进入我们熟悉的领域:producer调用了子类的 run, 而 run 创建了sink类,sink类调用自己的run方法实现了_subscribeHandler(AnyObserver(self))方法,而此时sink已经持有了connection方法

现在_subscribeHandler(AnyObserver(self))方法已经被调用了,也就是说我们封装在闭包里的请求方法已经被调用了。之后的问题就在于onNext方法是怎么实现的。
我们查看onNext的实现

image.png
依然是我们熟悉的on方法的调用,并把.next作为事件传了进去,继续点进去 image.png
又到了AnyObserver的on方法。接下来,就是我们陌生的领域
如果之前你留意过的话,这里能知道这个self.observer其实就是connection.on方法。而这里的意思就是把event方法作为参数传入connection.on方法。
我们再回到connection.on方法中,实现如下: image.png

还记得这个subjectObserver类吗,这就是前文提到的subject类。也就是说调用connection.on方法,其实就是调用了subject类的on方法。我们继续看这个subject类的on方法


我们前文提到过,这个_observers就是Bag。那们点进去看这个dispatch
image.png
是不是突然就什么都明白了。在这个dispatch方法里,遍历了我们之前存储的observer,而onNext作为参数传了进去,从而实现了订阅。

总结

一:publish存储了观察者闭包并创建了一个PublishSubject类。
二:PublishSubject类又存储了所有的订阅。
三:当调用connect方法时,第一步实现了观察者闭包,第二步遍历PublishSubject类里存储的订阅,并把把观察者闭包里的.onNext之类的核心方法作为参数,传入其中,从而实现订阅。

上一篇 下一篇

猜你喜欢

热点阅读