RACSignal 冷信号和热信号底层实现分析2_第1页
RACSignal 冷信号和热信号底层实现分析2_第2页
RACSignal 冷信号和热信号底层实现分析2_第3页
RACSignal 冷信号和热信号底层实现分析2_第4页
RACSignal 冷信号和热信号底层实现分析2_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

/冷信号和热信号底层实现分析前言由于最近在写关于底层实现分析的文章,当然也逃不了关于冷热信号操作的分析。这篇文章打算分析分析如何从冷信号转成热信号的底层实现。目录1.关于冷信号和热信号的概念2热信号3冷信号4.冷信号是如何转换成热信号的一.关于冷信号和热信号的概念冷热信号的概念是源自于源于框架()中的和,是主动的,尽管你并没有订阅事件,但是它会时刻推送,就像鼠标移动;而是被动的,只有当你订阅的时候,它才会发布消息。可以有多个订阅者,是一对多,集合可以及订阅者共享信息;而只能一对一,当有不同的订阅者,消息是重新完整发送。热信号是主动的,即使你没有订阅事件,它仍然会时刻推送。而冷信号是被动的,只有当你订阅的时候,它才会发送消息。热信号可以有多个订阅者,是一对多,信号可以及订阅者共享信息。而冷信号只能一对一,当有不同的订阅者,消息会从新完整发送。二.热信号家族中符合热信号的特点的信号有以下几个。1:<>(,,)*;(,,)*;-():((^)(<>));+();首先来看看的定义。是继承自,并且它还遵守协议。这就意味着它既能订阅信号,也能发送信号。在里面有一个数组,里面装着该信号的所有订阅者。其次还有一个信号,里面装着该信号所有订阅者的。之所以能称之为热信号,那么它肯定是符合上述热信号的定义的。让我们从它的实现来看看它是如何符合的。-(*):(<>){();*=[];=[[]];*=;(){[];}[:^{(){=[:^(<>,,*){;}];()[];}}];}上面是的实现,它和最大的不同在这两行*=;(){[];}把它的所有订阅者全部都保存到了的数组里。既然保存了所有的订阅者,那么,,就需要发生改变。-():(){[:^(<>){[];}];}-():(*){[];[:^(<>){[];}];}-(){[];[:^(<>){[];}];}从源码可以看到,中的,,都会执行:方法。-():((^)(<>)){*;(){=[];}(<>){();}}:方法会取出所有的订阅者,依次调用入参的()方法。关于的订阅和发送的流程可以参考第一篇文章,大体一致,其他的不同就是会依次对自己的订阅者发送信号。就满足了热信号的特点,它即使没有订阅者,因为自己继承了协议,所以自己本身就可以发送信号。冷信号只能被订阅了才能发送信号。可以有很多订阅者,它也会把这些订阅者都保存到自己的数组里。之后再发送信号,订阅者就如同一起看电视,播放过的节目就看不到了,发送过的信号也接收不到了。接收信号。而发送信号,订阅者接收信号都只能从头开始接受,如同看点播节目,每次看都从头开始看。2.:(,,)<>;+():(<>);先看看的定义。是在这个方法里面被用到的。-(*):(<>(^)()):((^)())在这个方法里面,里面最后里面是由发送信号。[?(x):x];关于的详细分析请看这篇文章3.:(,);+():();这个信号里面存储了一个对象,这里存储着这个信号的最新的值。当然也可以调用类方法+():(){*=[];=;;}在这个方法里面存储默认的值,如果没有接受到任何值,那么这个信号就会发送这个默认的值。当被订阅:-(*):(<>){*=[];*=[:^{(){[];}}];[:^{[];[];}];}里面会始终发送存储的值。调用会调用里面的,也会依次发送信号值给订阅数组里面每个订阅者。当向订阅者的时候:-():(){(){=;[];}}会把发送的值更新到里面。下次发送值就会发送最后更新的值。4.=;:(,,);(,,)*;(,);(,);(,)*;+():();中会存储大小的历史值。+():(){[(*)[]];}-(){[];}-():(){=[];();=;=(?[]:[]);;}在初始化中会初始化一个大小的数组。-(*):(<>){*=[];*=[:^{(){(){();[:(?:)];}();(){[];}(){[];}{*=[];[];}}}];[];;}当被订阅的时候,会把数组里面的值都发送出去。-():(){(){[?:];[];(>){[(0,-)];}}}在中,会保存每次接收到的值。调用的,会依次把值都发送到每个订阅者中。这里还会判断数组里面存储了多少个值。如果存储的值的个数大于了,那么要移除掉数组里面从0开始的前几个值,保证数组里面只装个数的值。和的区别在于,还会把历史的信号值都存储起来发送给订阅者。这一点,更像是和的合体版。是冷信号,一旦被订阅就会向订阅者发送所有的值,这一点和是一样的。但是又有着的特性,会把所有的值发送给多个订阅者。当发送完之前存储的历史值之后,之后再发送信号的行为就和完全一致了。三.冷信号在v2.5中除了信号以外,还有一些特殊的冷信号。1:+(*);这个信号只有一个方法。+(*){[[[]]""];;;(,^{=[[]];});;}在模式下,返回一个名字叫的信号。在模式下,返回一个单例的信号。-(*):(<>){();[:^{[];}];}信号一旦被订阅就会发送。2.:(,,);+(*):();信号的定义也很简单,直接根据的值返回一个。+(*):(){(){*;;(,^{=[[]];>=;});;}(){*;;(,^{=[[]];>=;});;}*=[[]];>=;[":",];;}在模式下直接新建一个信号里面的值存储的是入参。在模式下,会依照的值是否是空,来新建对应的单例。-(*):(<>){();[:^{[];[];}];}在被订阅的时候,就只会发送一个值的信号,发送完毕之后就。3.这个信号是创建:的真身。关于详细过程请看第一篇文章。4.:(,,)*;+(*):(*);信号里面就存储了一个。+(*):(*){*=[[]];>=;[":",];=@":";;}初始化的时候把外界传进来的保存起来。当被订阅的时候就发送这个出去。5.:<>-()((("a")));(,,)*;(,,)<>;-():(*):(<>);在日常开发中,用来双向绑定的。它和一样,既继承自,同样又遵守协议。虽然具有的发送和接收信号的特性,但是它依旧是冷信号,因为它无法一对多,它发送信号还是只能一对一。无法手动初始化,需要靠去初始化。-(){=[];();*=[[:0]""];*=[[:1]""];[[]];[[]];=[[[]]""];=[[[]]""];;}在的初始化中会调用的:方法,这里的入参都是类型的。所以订阅过程的时候:-(*):(<>){[];}其实就是一个,就相当于订阅。订阅过程同上面的订阅过程。-():(){[];}-():(*){[];}-(){[];}也是类型的,管道两边都是类型的信号。当开始,,是调用的管道另外一个的进行这些对应的操作的。平时使用的地方在和的双向绑定上面。例如在登录界面,输入密码文本框和的双向绑定*=[];*=(,136);[];[];双向绑定的两个信号都会因为对方的改变而收到新的信号。至此所有的的分类就都理顺了,按照冷信号和热信号的分类也分好了。根据订阅和发送信号的流程,我们可以知道,每订阅一次冷信号,就会执行一次闭包。这个时候就是可能出现问题的地方。如果是被用于网络请求,那么在闭包里面会被重复的请求。上面文中提到了信号被订阅了6次,网络请求也会请求6次。这并不是我们想要的。网络请求只需要请求1次。如何做到信号只执行一次闭包,最重要的一点是冷信号只能被订阅一次。由于冷信号只能一对一,那么想一对多就只能交给热信号去处理了。这时候就需要把冷信号转换成热信号。在v2.5中,冷信号转换成热信号需要用到这个类。:(,,)*;-(*);-(*);(){*;32;}(,,)*;()*;看看类的定义。最主要的是保存了两个信号,一个是,一个是(类型)。在中暴露给外面的是,在中实际使用的是。看它的定义就能猜到接下去它会做什么:用去发送信号,内部再用去订阅,然后会把的信号值依次发给它的订阅者们。用一个不恰当的比喻来形容,它就像上图中心的那个“地球”,“地球”就是订阅了的,把值发送给各个“连接”者(订阅者)。只有内部的一个订阅者,所以就完成了我们只想执行闭包一次,但是能把值发送给各个订阅者的愿望。在看看的初始化-():(*):(*){();();=[];();=;=[[]];=;;}初始化方法就是把外界传进来的保存成,把外界传进来的保存成自己的属性。有两个连接方法。-(*){=32(0,1,);(){=[];};}这里出现了一个不多见的函数32,它是原子运算的操作符,主要用于,原型如下:32(32,32,32*);关键字只确保每次获取变量时都是从内存加载变量,而不是使用寄存器里面的值,但是它不保证代码访问变量是正确的。如果用伪代码去实现这个函数:f(*){*=;1;}{0;}如果为0,意味着没有连接,32返回1,就应该连接。如果为1,意味着已经连接过了,32返回0,不会再次连接。所谓连接的过程就是内部用订阅。是,会把订阅者保存到中,的时候就会调用,这时就会把的信号都发送给各个订阅者了。-(*){32=0;[[:^(<>){32();*=[];*=[];[:^{[];(32()0){[];}}];}]"[]",];}32和32也是原子运算的操作符,分别是+1和-1操作。在为了保证线程安全,用到了一个的类似信号量的变量,保证第一个订阅者能连接上。返回的新的信号的订阅者订阅,也会去订阅内部的。把冷信号转换成热信号用以下5种方式,5种方法都会用到。接下来一一分析它们的具体实现。1.:-(*):(*){["[]:",,];*=[[]];;}:的操作就是初始化一个对象,是,内部的是入参。*=[:[]];[:^(x){(@"");}];[];调用:把冷信号转换成热信号有一个点不方便的是,需要自己手动。注意转换完之后的热信号在的属性中,所以需要订阅的是。2.-(*){*=[[]"[]",];*=[];;}方法只不过是去调用了:方法,内部会新建好一个,并把它当成入参传递给。*=[];[:^(x){(@"");}];[];同样方法也需要手动的调用方法。3.-(*){*=[[]"[]",];*=[];[];;}方法会把当成的传递进去,初始化好了,再自动调用方法,返回的信号就是转换好的热信号,即里面的信号。这里必须是,因为在方法里面先了。如果用,那信号在之后就会通过把原信号发送给各个订阅者了。用把信号保存起来,即使方法里面先,订阅者后订阅也是可以拿到之前的信号值的。4.-(*){

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论