Subject

Subject可以看成是一个桥梁或者代理,在某些ReactiveX实现中(如RxJava),它同时充当了Observer和Observable的角色。因为它是一个Observer,它可以订阅一个或多个Observable;又因为它是一个Observable,它可以转发它收到(Observe)的数据,也可以发射新的数据。

由于一个Subject订阅一个Observable,它可以触发这个Observable开始发射数据(如果那个Observable是"冷"的--就是说,它等待有订阅才开始发射数据)。因此有这样的效果,Subject可以把原来那个"冷"的Observable变成"热"的。

Subject的种类

针对不同的场景一共有四种类型的Subject。他们并不是在所有的实现中全部都存在,而且一些实现使用其它的命名约定(例如,在RxScala中Subject被称作PublishSubject)。

AsyncSubject

一个AsyncSubject只在原始Observable完成后,发射来自原始Observable的最后一个值。(如果原始Observable没有发射任何值,AsyncObject也不发射任何值)它会把这最后一个值发射给任何后续的观察者。

然而,如果原始的Observable因为发生了错误而终止,AsyncSubject将不会发射任何数据,只是简单的向前传递这个错误通知。

BehaviorSubject

当观察者订阅BehaviorSubject时,它开始发射原始Observable最近发射的数据(如果此时还没有收到任何数据,它会发射一个默认值),然后继续发射其它任何来自原始Observable的数据。

然而,如果原始的Observable因为发生了一个错误而终止,BehaviorSubject将不会发射任何数据,只是简单的向前传递这个错误通知。

PublishSubject

PublishSubject只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者。需要注意的是,PublishSubject可能会一创建完成就立刻开始发射数据(除非你可以阻止它发生),因此这里有一个风险:在Subject被创建后到有观察者订阅它之前这个时间段内,一个或多个数据可能会丢失。如果要确保来自原始Observable的所有数据都被分发,你需要这样做:或者使用Create创建那个Observable以便手动给它引入"冷"Observable的行为(当所有观察者都已经订阅时才开始发射数据),或者改用ReplaySubject。

如果原始的Observable因为发生了一个错误而终止,PublishSubject将不会发射任何数据,只是简单的向前传递这个错误通知。

ReplaySubject

ReplaySubject会发射所有来自原始Observable的数据给观察者,无论它们是何时订阅的。也有其它版本的ReplaySubject,在重放缓存增长到一定大小的时候或过了一段时间后会丢弃旧的数据(原始Observable发射的)。

如果你把ReplaySubject当作一个观察者使用,注意不要从多个线程中调用它的onNext方法(包括其它的on系列方法),这可能导致同时(非顺序)调用,这会违反Observable协议,给Subject的结果增加了不确定性。

RxJava的对应类

假设你有一个Subject,你想把它传递给其它的代理或者暴露它的Subscriber接口,你可以调用它的asObservable方法,这个方法返回一个Observable。具体使用方法可以参考Javadoc文档。

串行化

如果你把 Subject 当作一个 Subscriber 使用,注意不要从多个线程中调用它的onNext方法(包括其它的on系列方法),这可能导致同时(非顺序)调用,这会违反Observable协议,给Subject的结果增加了不确定性。

要避免此类问题,你可以将 Subject 转换为一个 SerializedSubject ,类似于这样:

mySafeSubject = new SerializedSubject( myUnsafeSubject );

RxJava Subject的更多相关文章

  1. ReactiveX--响应式编程の相关概念 浅析

    在许多软件编程任务中,你或多或少期待你的指令将会按照你已经写好的顺序,依次增量执行和完成.但在ReactiveX,很多指令可以通过“观察者”并行执行,其结果将以任意顺序被捕获.你定义了一种“可观察的形 ...

  2. RXJAVA之Subject

    RxJava中常见的Subject有4种,分别是 AsyncSubject. BehaviorSubject.PublishSubject. ReplaySubject. AsyncSubject 使 ...

  3. Android消息传递之基于RxJava实现一个EventBus - RxBus

    前言: 上篇文章学习了Android事件总线管理开源框架EventBus,EventBus的出现大大降低了开发成本以及开发难度,今天我们就利用目前大红大紫的RxJava来实现一下类似EventBus事 ...

  4. Rxjava Subjects

    上次提到调用observable的publish和connect方法后可以将一个Observable发出的对象实时传递到订阅在上的subscriber. 这个和Rxjava中Subject的概念十分相 ...

  5. RxJava简单的介绍

    1. RxJava简介 Rx(ReactiveX,响应式编程)是一种事件驱动的基于异步数据流的编程模式,整个数据流就像一条河流,它可以被观测(监听),过滤,操控或者与其他数据流合并为一条新的数据流.而 ...

  6. [RxJava^Android]项目经验分享 --- RxLifecycle功能实现分析(一)

      最近在研究RxJava自定义操作符的实现原理,发现成型的项目案例较少.突然想起在项目中应用的RxLifecycle是使用自定义操作符,便拿来研究了一下.分析之前,跟大家了解一些相关操作符和RxLi ...

  7. [Android]基于RxJava、RxAndroid的EventBus实现

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4578699.html  Github:https://gith ...

  8. RxJava 和 RxAndroid 一 (基础)

    1.RxJava 项目地址 https://github.com/ReactiveX/RxJava 2.RxAndroid 项目地址    https://github.com/ReactiveX/R ...

  9. Android--Retrofit+RxJava的简单封装(三)

    1,继续接着上一篇的讲讲,话说如果像上一篇这样的话,那么我们每一次请求一个结构都要创建一堆的Retrofit对象,而且代码都是相同的,我们可以试试封装一下 先创建一个HttpMethods类,将Ret ...

随机推荐

  1. 为nginx配置https并自签名证书

    一.把证书准备好. 步骤与使用OpenSSL自签发服务器https证书所述大同小异.在这里再重复一次. 1.制作CA证书: ca.key CA私钥: openssl genrsa -des3 -out ...

  2. Delphi idHttpServer接收Http Get请求解码问题

    引用 Httpapp单元,使用Httpdecode函数进行解码 procedure TFrmMain.HTTPServerCommandGet(AThread: TIdPeerThread; AReq ...

  3. SGU 205. Quantization Problem

    205. Quantization Problem time limit per test: 0.25 sec. memory limit per test: 65536 KB input: stan ...

  4. day1作业一:编写登陆接口

    作业一:编写登陆接口 1.输入用户名和密码 2.认证成功后显示欢迎信息 3.输错三次后锁定 Readme: (1)提示用户输入用户名: (2)用户名验证,验证是否已经锁定: (3)是否锁定:已锁定告诉 ...

  5. [转]C/C++关于全局变量和局部变量初始化与不初始化的区别

    原文链接:http://www.kingofcoders.com/viewNews.php?type=newsCpp&id=189&number=4836955386 在C语言里,全局 ...

  6. lua常用函数

    select (index, ···) 功能:当index为数字将返回所有index大于index的参数: 如:select(2,"a","b","c ...

  7. 在phpWeChat里生成一个临时二维码(非微信二维码)

    phpWeChat作为支持Pc+H5开发的管理系统,内置一套二维码生成API,访问地址: 您的域名/api/qrcode/index.php?data=二维码数据 以下为使用示例 使用时有一点需要注意 ...

  8. python解析Nginx访问日志

    环境说明 python3+ pip install geoip2==2.9.0 nginx日志配置成json格式,配置如下: log_format json_log '{ "time&quo ...

  9. TCP/IP——ARP与RARP简记

    ARP(Address Resolution Protocol):ARP为IP地址到对应的硬件地址(MAC)之间提供动态映射.这个过程是自动完成的,一般应用程序用户和系统管理员不必要关心. ARP高速 ...

  10. SCOI2011 棘手的操作

    线段树+并查集,对于每个操作我们只需要维护他在自己子树中的最值和在整个树里的最值,类似于线段树动态开点. #include<bits/stdc++.h> using namespace s ...