RAC中Multicast的实现原理分析
来源:互联网 发布:手机玩lol软件 编辑:程序博客网 时间:2024/04/30 13:48
1. 为什么要用Multicast?
RACMulticastConnection类的注释如下:
/// A multicast connection encapsulates the idea of sharing one subscription to a/// signal to many subscribers. This is most often needed if the subscription to/// the underlying signal involves side-effects or shouldn't be called more than/// once.
从注释中可以知道,Multicast的作用是让side effect代码只被执行一次。我们知道,普通Signal每次被subscribe,都会执行side effect代码。如果side effect代码性能开销很大并且重复执行结果相同,那么确保side effect代码只被执行一次就很有意义,Multicast就是做的这个事情。
2. Multicast是如何确保side effect代码只被执行一次?
为了解答这个问题,我们要知道为什么普通Signal每次被subscribe,都会执行side effect代码。
一般,我们会调用下面这个方法创建Signal,所有的side effect代码的都包含在didSubscribe这个Block中。
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe;
Signal在被subscribe的时候会执行这个Block,源码如下(省略非关键代码):
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber { 、、、 RACDisposable *innerDisposable = self.didSubscribe(subscriber); 、、、}
我们调用doNext、flatten、concat等Operation对Signal进行变换,内部多是创建一个新的Signal,这个新的Signal的didSubcribe中会subscirbe要变换的Signal。所以使用Operation对Signal进行变换得到的Signal,被subscribe的时候会一层一层向上去subscribe最原始的Signal,一层一层向上去执行didSubscribe Block,最终所有的side effect代码都会被执行。
那么Multicast是如何做到side effect仅被执行一次的?
注释是这么说的A multicast connection encapsulates the idea of sharing one subscription to a signal to many subscribers.
。看源码可以知道,内部是利用RACSubject在中间转发消息,RACSubject(_signal
)订阅真正的Signal(sourceSignal
),外部Subscribers订阅RACSubject(_signal
),如下图所示:
源码如下(省略非关键代码):
- (RACDisposable *)connect { BOOL shouldConnect = OSAtomicCompareAndSwap32Barrier(0, 1, &_hasConnected); if (shouldConnect) { self.serialDisposable.disposable = [self.sourceSignal subscribe:_signal]; } return self.serialDisposable;}- (RACSignal *)autoconnect { 、、、 return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) { 、、、 RACDisposable *subscriptionDisposable = [self.signal subscribe:subscriber]; RACDisposable *connectionDisposable = [self connect]; 、、、 }] setNameWithFormat:@"[%@] -autoconnect", self.signal.name];}
从上面源码还可以看出,autoconnect是lazy的,有外部订阅者订阅的时候,才调用connect方法,让subject订阅sourceSignal。
这里的关键是RACSubject,它既是sourceSignal的订阅者,也是外部subscribers的数据源。RACSubject会被订阅多次,而sourceSignal只会被订阅一次,它的didSubscribe Block只会被执行一次,只会产生一次副作用。
- RAC中Multicast的实现原理分析
- RAC的实现原理
- RAC原理分析
- oracle rac 负载的实现原理
- 基于IP Multicast的传输和实现
- Java中HashMap的实现原理分析
- RAC 中GES/GCS原理
- 关于RAC中SCN原理和机制的探索
- skynet学习笔记【skynet multicast服务的实现】
- 深入分析Java并发中volatile的实现原理
- 深入分析Java并发中volatile的实现原理
- C#中多重委托(Multicast Delegate)的例子
- iOS Reactivecocoa(RAC)原理分析
- RAC 的基本概念和原理
- RAC的GES/GCS原理
- OgreTerrain的实现原理分析
- ConcurrentLinkedQueue的实现原理分析
- ConcurrentLinkedQueue的实现原理分析
- 增长黑客
- Fiddler使用
- 开始博客之路
- 六种方式实现hibernate查询
- ViewTreeObserver
- RAC中Multicast的实现原理分析
- 程序设计进阶 编程题#4:Tomrrow never knows?
- spoj D-query 区间不同数个数 主席树||离线+树状数组
- 一个案例教你简单地玩转ViewPager(二)之ViewPaper+TabLayout+Fragment顶部标签界面滑动
- 我的感想
- 【op】tomcat部署服务器步骤
- Python 中的 None 与真假
- Eclipse下修改Android里的apk包名
- 斯坦福机器学习笔记-Lecture 1,2