RAC中Multicast的实现原理分析
2016-08-27 16:08
477 查看
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 cache fusion机制实现原理分析
- RAC cache fusion机制实现原理分析
- 从源码角度分析RACObserve的实现原理(一)
- [转]asp.net中利用ashx实现图片防盗链的原理分析
- MFC工具条和状态栏,内部实现原理详细分析
- asp.net中利用ashx实现图片防盗链的原理分析
- ASP程序实现图片上传的原理分析
- Hibernate实现分页查询的原理分析zz
- [技术学习]配合APUE学习贴篇select实现原理分析
- ASP实现图片上传原理分析及示例
- 各种算法的C#实现系列1 - 合并排序的原理及代码分析
- 一个小语言的词法分析程序原理及其实现(2)
- 从eboot菜单分析eboot功能实现原理
- ASP文件上传原理分析及实现实例
- asp.net中利用ashx实现图片防盗链的原理分析
- ARP欺骗技术实现原理分析
- IronPython for ASP.NET 的原理分析(一):如何在 CLR 类型上实现动态性
- 简略的分析一下Anthem无刷新控件的实现原理和流程
- Java对象池技术的原理及其实现 --Java对象的生命周期分析