前言

Subject是一个代理,它既是Observer,也是Observable。因为它是一个Observer,它可以订阅一个或多个Observable;因为它是一个Observable,它又可以被其他的Observer订阅。它可以传递/转发作为Observer收到的值,也可以主动发射值。

SubjectRxSwift中的实现有四种:

  • PublishSubject
  • ReplaySubject
  • BehaviorSubject
  • Variable

PublishSubject

代理

我们先以PublishSubject为例来解释Subject是一个代理的含义。

let subject = PublishSubject<Int>()
subject.subscribe({ (event) in
print("Event:\(event)")
}) subject.onNext(1)
subject.onNext(2)
subject.onCompleted()

Subject作为一个Observable提供了subscribe等方法。在订阅之后,我们调用了onNext(),向Observer发射了12,以及onCompleted()。打印结果和我们预期的是一样的。

Event:next(1)
Event:next(2)
Event:completed

我们可以调用Subjecton系列方法主动给Observer发送值。

Subject可以作为代理转发订阅到的结果。例如:

let subject = PublishSubject<Int>()
subject.subscribe({ (event) in
print("Event:\(event)")
}) let reveseSubject = Observable<Int>.create({ (observer) -> Disposable in
observer.onNext(1)
observer.onNext(2)
observer.onCompleted() return Disposables.create()
}) reveseSubject.subscribe(subject)

subject订阅了reveseSubject,并将结果转发给了Observer

注意:Observer订阅 subject时不会收到订阅之前subject的值。

let subject = PublishSubject<Int>()
subject.onNext(0)
subject.subscribe({ (event) in
print("Event:\(event)")
}) subject.onNext(1)
subject.onNext(2)
subject.onCompleted()

上述代码结果为:

Event:next(1)
Event:next(2)
Event:completed

observer无法接收到0这个值。

ReplaySubject

ReplaySubjectPublishSubject不同的是,Observer有可能接收到订阅之前的值。

let subject = ReplaySubject<Int>.create(bufferSize: 1)

    subject.onNext(0)
subject.subscribe({ (event) in
print("Event:\(event)")
}) subject.onNext(1)
subject.onNext(2)
subject.onCompleted()

上述代码结果为:

Event:next(0)
Event:next(1)
Event:next(2)
Event:completed

ReplaySubject具有重放(replay)的功能,replay的个数可以通过参数指定。我们可以将其理解为缓存的效果。

一般我们使用ReplaySubject的时候,都是先发射,后订阅,然后通过指定缓存的大小,可以获取对应的值。(注意:不考虑Error和Completed)。

let subject = ReplaySubject<Int>.create(bufferSize: 1)

subject.onNext(0)
subject.onNext(1)
subject.onNext(2)
subject.onCompleted() subject.subscribe({ (event) in
print("Event:\(event)")
})

上述代码,我们指定了bufferSize等于1,所以只缓存了最新的值,打印结果:

Event:next(2)
Event:completed

当我们需要缓存所有值的时候,可以调用createUnbounded()方法。

ReplaySubject.create(bufferSize: 0) 等同于 PublishSubject()。

BehaviorSubject

BehaviorSubject类似于ReplaySubject具有缓存能力,但是略有不同。

  • 只缓存一个最新值,类似ReplaySubject.create(bufferSize: 1)
  • 需要提供默认值
let behaviorSubject = BehaviorSubject<Int>(value: 1)
behaviorSubject.subscribe({ (event) in
print("Event:\(event)")
})

打印结果为:

Event:next(1)

使用BehaviorSubject有一点好处,我们可以确定当Observer订阅时,至少可以收到最新的一个值。

Variable

VariableBehaviorSubject又很相似,VariableBehaviorSubject的一个封装,同样具备了缓存最新值和提供默认值的能力。但是Variable没有on系列方法,只提供了value属性。

直接对value进行set等同于调用了onNext()方法。

这表明了Variable不会发射error也不会发射completed

Variable被销毁的时候会调用发射completedObserver

在订阅Variable的时候,我们无法直接调用subscribe方法,需要先调用asObservable()方法。

let variable = Variable<Int>(1)
variable.asObservable().subscribe({ (event) in
print("Event:\(event)")
})
variable.value = 2

上述结果为:

Event:next(1)
Event:next(2)
Event:completed

Variable可以用来储存数据,因为我们可以拥有valuegetset方法。比如:

let variable = Variable(1)
print("Value: \(variable.value)")
variable.value = 2
print("Value: \(variable.value)")

打印结果为:

Value: 1
Value: 2

这是BehaviorSubject不具备的。

RxSwift 系列(二) -- Subject的更多相关文章

  1. RxSwift 系列(二)

    前言 Subject是一个代理,它既是Observer,也是Observable.因为它是一个Observer,它可以订阅一个或多个Observable;因为它是一个Observable,它又可以被其 ...

  2. sed修炼系列(二):sed武功心法(info sed翻译+注解)

    sed系列文章: sed修炼系列(一):花拳绣腿之入门篇sed修炼系列(二):武功心法(info sed翻译+注解)sed修炼系列(三):sed高级应用之实现窗口滑动技术sed修炼系列(四):sed中 ...

  3. Newtonsoft.Json C# Json序列化和反序列化工具的使用、类型方法大全 C# 算法题系列(二) 各位相加、整数反转、回文数、罗马数字转整数 C# 算法题系列(一) 两数之和、无重复字符的最长子串 DateTime Tips c#发送邮件,可发送多个附件 MVC图片上传详解

    Newtonsoft.Json C# Json序列化和反序列化工具的使用.类型方法大全   Newtonsoft.Json Newtonsoft.Json 是.Net平台操作Json的工具,他的介绍就 ...

  4. 前端构建大法 Gulp 系列 (二):为什么选择gulp

    系列目录 前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gul ...

  5. WPF入门教程系列二十三——DataGrid示例(三)

    DataGrid的选择模式 默认情况下,DataGrid 的选择模式为“全行选择”,并且可以同时选择多行(如下图所示),我们可以通过SelectionMode 和SelectionUnit 属性来修改 ...

  6. Web 开发人员和设计师必读文章推荐【系列二十九】

    <Web 前端开发精华文章推荐>2014年第8期(总第29期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...

  7. Web 前端开发人员和设计师必读文章推荐【系列二十八】

    <Web 前端开发精华文章推荐>2014年第7期(总第28期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...

  8. Web 开发精华文章集锦(jQuery、HTML5、CSS3)【系列二十七】

    <Web 前端开发精华文章推荐>2014年第6期(总第27期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...

  9. Web 前端开发人员和设计师必读精华文章【系列二十六】

    <Web 前端开发精华文章推荐>2014年第5期(总第26期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...

随机推荐

  1. 浅谈Windows下SVN在Android Studio中的配置、基本使用及解除关联

    看到网上很多关于svn环境配置和关联Android-Studio的很多博文,发现很零散,想集大家所长整理一下: 在AndroidStudio中开发版本控制中,除了Git就是SVN,和Eclipse不同 ...

  2. jquery不兼容input的change事件处理

    因为客户使用系统一般都是用IE版本的浏览器,所以每次在chrome下调试之后都要在IE走一遍; 这次准备在选择开始时间或者结束时间之后在下方能及时给出对应的天数,但是在IE8下试了change时间根本 ...

  3. CVE-2017-8464远程命令执行漏洞(震网漏洞)复现

    前言 2017年6月13日,微软官方发布编号为CVE-2017-8464的漏洞公告,官方介绍Windows系统在解析快捷方式时存在远程执行任意代码的高危漏洞,黑客可以通过U盘.网络共享等途径触发漏洞, ...

  4. vue组件大集合 component

    vue组件分为全局组件.局部组件和父子组件,其中局部组件只能在el定义的范围内使用, 全局组件可以在随意地方使用,父子组件之间的传值问题等. Vue.extend 创建一个组件构造器 template ...

  5. Linux 中最常用的目录及文件管理命令

    一.查看文件的命令 对于一个文本文件,在linux中有多种查看方式来获知文件内容,如直接显示整个文本内容.分页查看内容.或者只查看文件开头或末尾的部分内容.在linux可以用不同的命令来实现. 1. ...

  6. [leetcode-553-Optimal Division]

    Given a list of positive integers, the adjacent integers will perform the float division. For exampl ...

  7. 关于Client_Abort_Exception异常的分析和解决

    1.什么情况下会出现“ClientAbortException:  java.net.socketException:  Broken pipe”? 答:客户端非正常(标准握手协议)退出连接,体现在h ...

  8. 程序员必须知道的六大ES6新特性

    二 .字符串扩展 1.传统上,JavaScript只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中.ES6又提供了三种新方法. includes():返回布尔值,表示是否找到了参 ...

  9. webpack教程(二)——webpack.config.js文件

    首先我们需要安装一个webpack插件html-webpack-plugin,该插件的作用是帮助我们生成创建html入口文件.执行如下命令 npm install html-webpack-plugi ...

  10. Linux进阶命令-sort、uniq、 cut、sed、grep、find、awk

    命令难度总体来说有简入难,参数都是工作中常常用到的.如果涉及到一些生僻的参数还请百度或man一下. sort(参考学习网站:http://www.cnblogs.com/dong008259/arch ...