一需求
开发中有时候会碰到一种需求:当某一个网络请求正在请求的过程中,别的地方又发起同样的一个网络请求,此时要求不再发送同样的请求,而正在发生的请求拿到数据后要返回给两个发起者,如图
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类,并传入了两个参数:AnonymousObservable和subject。AnonymousObservable我们已经非常熟悉,至于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类③核心方法,其实也就是调用了
producer的subscribe方法。④
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之类的核心方法作为参数,传入其中,从而实现订阅。











网友评论