create

Observable分为cold以及hot两种,cold主要是静态的,每次subscribe都是从头开始互不干扰,而hot的在同一时刻获得的值是一致的

cold Observable

使用create创建的Observable都是属于cold的Observable

@Test
public void coldObs() throws InterruptedException {
Observable obs=Observable.create(sub->{
//在新线程上emit对象
new Thread(()->{
int i=0;
while(i<5){
sub.onNext(i++);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}}).start();
});
obs.subscribe(x->System.out.println("1st sub "+x));
Thread.sleep(1000);
obs.subscribe(x->System.out.println("2nd sub "+x));
while(true){
Thread.sleep(10000);
}
}
-----输出-----
1st sub 0
1st sub 1
2nd sub 0
1st sub 2
2nd sub 1
1st sub 3
2nd sub 2
1st sub 4
2nd sub 3
2nd sub 4

可以看到两个subscribe相隔1s订阅,两个值互不相关。

hot Observable

coldObs可以转换为hotObservable,hot主要是使用在比如鼠标操作等事件上的

@Test
public void hotObs() throws InterruptedException {
ConnectableObservable obs=Observable.create(sub->{
//在新线程上emit对象
new Thread(()->{
int i=0;
while(i<5){
sub.onNext(i++);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}}).start();
}).publish();
//开始emit对象
obs.connect();
obs.subscribe(x->System.out.println("1st sub "+x));
Thread.sleep(1000);
obs.subscribe(x->System.out.println("2nd sub "+x));
while(true){
Thread.sleep(10000);
}
}
-----输出-----
1st sub 1
1st sub 2
1st sub 3
2nd sub 3
1st sub 4
2nd sub 4

使用publish和connect之后就开始向subscriber发送对象,无论当前有几个subscriber,同一时刻subscriber得到的值也是一样的

源码分析

RxJava中有内置的钩子函数可以将函数注册在RxJavaHooks的各个方法上来改变各个环节的操作,包括Observable创建,运行时等

Observable的create方法只是注册了对应emit的OnSubscribe对象

    public static <T> Observable<T> create(OnSubscribe<T> f) {
//调用protected构造方法,这里使用RxJavaHooks的onCreate方法
return new Observable<T>(RxJavaHooks.onCreate(f));
}
protected Observable(OnSubscribe<T> f) {
this.onSubscribe = f;
}

正真运行Observable的是subscriber订阅时触发的

public final Subscription subscribe(Subscriber<? super T> subscriber) {
return Observable.subscribe(subscriber, this);
} static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
if (subscriber == null) {
throw new IllegalArgumentException("subscriber can not be null");
}
if (observable.onSubscribe == null) {
throw new IllegalStateException("onSubscribe function can not be null.");
} //调用subscriber的onStart方法
subscriber.onStart(); //使用SafeSubscriber包装原有的Subscriber,SafeSubscriber装饰原来的Subscriber保证当调用onComplete或onError后不会再调用任何方法。
if (!(subscriber instanceof SafeSubscriber)) {
subscriber = new SafeSubscriber<T>(subscriber);
} try {
//使用JavaHooks的onObservableStart拦截的onSubscribe,并调用subscriber
RxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber);
//当结束调用RxJavaHooks的onObservableReturn拦截方法
return RxJavaHooks.onObservableReturn(subscriber);
} catch (Throwable e) {
...
}
}

这个是cold Observable的流程,下面看下Observable的publish和connect的逻辑

//Observable.java
//publish方法包装原来的Observable返回ConnectableObservable
public final ConnectableObservable<T> publish() {
return OperatorPublish.create(this);
} //OperatorPublish.java
public static <T> ConnectableObservable<T> create(Observable<? extends T> source) {
//订阅在原始Observable上的Subscriber
final AtomicReference<PublishSubscriber<T>> curr = new AtomicReference<PublishSubscriber<T>>();
//ConnectableObservable的OnSubscribe,提供外界Subscriber订阅
OnSubscribe<T> onSubscribe = new OnSubscribe<T>() {
@Override
public void call(Subscriber<? super T> child) {
for (;;) {
PublishSubscriber<T> r = curr.get();
if (r == null || r.isUnsubscribed()) {
//这个Subscriber是用于订阅到原始Observable上的,这里只是初始化,并没有开始订阅
PublishSubscriber<T> u = new PublishSubscriber<T>(curr);
u.init();
if (!curr.compareAndSet(r, u)) {
continue;
}
r = u;
} InnerProducer<T> inner = new InnerProducer<T>(r, child);
//将订阅的子subscriber添加到PublishSubscriber上
if (r.add(inner)) {
child.add(inner);
child.setProducer(inner);
break; // NOPMD
}
}
}
};
return new OperatorPublish<T>(onSubscribe, source, curr);
} //connect方法将PublishSubscriber订阅到原始的Observable,
//ConnectableObservble.java
public final Subscription connect() {
final Subscription[] out = new Subscription[1];
//调用OperatorPublish的connect方法
connect(new Action1<Subscription>() {
@Override
public void call(Subscription t1) {
out[0] = t1;
}
});
return out[0];
} //OperatorPublish.java
public void connect(Action1<? super Subscription> connection) {
boolean doConnect;
PublishSubscriber<T> ps;
//防止竞态条件使用CAS来初始化PublishSubscriber
for (;;) {
ps = current.get();
if (ps == null || ps.isUnsubscribed()) {
PublishSubscriber<T> u = new PublishSubscriber<T>(current);
u.init();
if (!current.compareAndSet(ps, u)) {
continue;
}
ps = u;
}
doConnect = !ps.shouldConnect.get() && ps.shouldConnect.compareAndSet(false, true);
break; // NOPMD
}
connection.call(ps);
if (doConnect) {
//如果之前没有订阅过,那么就订阅到原始的Observable上
source.unsafeSubscribe(ps);
}
} //PublishSubscriber.java
//这个是订阅到原始Observable上的Subscriber,当触发onNext时的逻辑
public void onNext(T t) {
//将原始Observable发出的对象放入一个队列
if (!queue.offer(NotificationLite.next(t))) {
onError(new MissingBackpressureException());
} else {
//调用dispatch方法可以将队列的内容发送个订阅的子Subscriber
dispatch();
}
} //将值分发到各个子Subscriber上
void dispatch() {
...
//从队列中取得值
Object v = queue.poll();
...
//处理null
T value = NotificationLite.getValue(v);
...
//循环所有的InnerProducer(之前的在onSubscribe中add在Subsciber上的)
for (InnerProducer<T> ip : ps) {
if (ip.get() > 0L) {
try {
//把value传递给child的onNext
ip.child.onNext(value);
} catch (Throwable t) {
ip.unsubscribe();
Exceptions.throwOrReport(t, ip.child, value);
continue;
}
ip.produced(1);
}
}
...
}

hot的Observable就是自己监听原始的Observable然后广播给注册在上的子Subscriber,从而达到能够让所有子Subscriber取得一样的数据。

Rxjava cold/hot Observable的更多相关文章

  1. RxJava 设计理念 观察者模式 Observable lambdas MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  2. RxJava && Agera 从源码简要分析基本调用流程(2)

    版权声明:本文由晋中望原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/124 来源:腾云阁 https://www.qclo ...

  3. Rxjava异常处理

    异常处理 在Rxjava订阅的Observable有时会抛出异常,在RxJava中有两大类策略,一个是准备备用的Observable,在发生异常时将subscriber订阅到新的Observable上 ...

  4. RxJava 和 RxAndroid 一 (基础)

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

  5. 用RxJava处理嵌套请求

    用RxJava处理嵌套请求 互联网应用开发中由于请求网络数据频繁,往往后面一个请求的参数是前面一个请求的结果,于是经常需要在前面一个请求的响应中去发送第二个请求,从而造成"请求嵌套" ...

  6. 78. Android之 RxJava 详解

    转载:http://gank.io/post/560e15be2dca930e00da1083 前言 我从去年开始使用 RxJava ,到现在一年多了.今年加入了 Flipboard 后,看到 Fli ...

  7. Retrofit与RXJava整合

    Retrofit 除了提供了传统的 Callback 形式的 API,还有 RxJava 版本的 Observable 形式 API.下面我用对比的方式来介绍 Retrofit 的 RxJava 版 ...

  8. RxJava学习入门

    RxJava是什么 一个词:异步. RxJava 在 GitHub 主页上的自我介绍是 "a library for composing asynchronous and event-bas ...

  9. 给 Android 开发者的 RxJava 详解

    我从去年开始使用 RxJava ,到现在一年多了.今年加入了 Flipboard 后,看到 Flipboard 的 Android 项目也在使用 RxJava ,并且使用的场景越来越多 .而最近这几个 ...

随机推荐

  1. npm 私有模块的管理使用

    你可以使用 NPM 命令行工具来管理你在 NPM 仓库的私有模块代码,这使得在项目中使用公共模块变的更加方便. 开始前的工作 你需要一个 2.7.0 以上版本的 npm ,并且需要有一个可以登陆 np ...

  2. JavaScript自定义浏览器滚动条兼容IE、 火狐和chrome

    今天为大家分享一下我自己制作的浏览器滚动条,我们知道用css来自定义滚动条也是挺好的方式,css虽然能够改变chrome浏览器的滚动条样式可以自定义,css也能够改变IE浏览器滚动条的颜色.但是css ...

  3. 1.初始Windows Server 2012 R2 Hyper-V + 系统安装详细

    干啥的?现在企业服务器都是分开的,比如图片服务器,数据库服务器,redis服务器等等,或多或少一个网站都会用到多个服务器,而服务器的成本很高,要是动不动采购几十台,公司绝对吃不消的,于是虚拟化技术出来 ...

  4. 解决vs创建或打开C++浏览数据库文件*.sdf时发生错误的问题

    VS2012,  创建或打开C++浏览数据库文件*.sdf时发生错误. IntelliSense 和浏览信息将不能用于C++项目. 请确保已安装 Microsoft SQL Server Compac ...

  5. Android公共title的应用

    我们在开发Android应用中,写每一个页面的时候都会建一个title,不是写一个LinearLayout就是写一个RelativeLayout,久而久之就会觉得这样繁琐,尤其几个页面是只是标题不一样 ...

  6. Could not evaluate expression

    VS15 调试变量不能显示值,提示:Could not evaluate expression 解决办法: 选择"在调试时显示运行以单击编辑器中的按钮"重启VS即可. 可参考:Vi ...

  7. bzoj3037--贪心

    题目大意: applepi手里有一本书<创世纪>,里面记录了这样一个故事--上帝手中有着N 种被称作"世界元素"的东西,现在他要把它们中的一部分投放到一个新的空间中去以 ...

  8. 编译器开发系列--Ocelot语言6.静态类型检查

    关于"静态类型检查",想必使用C 或Java 的各位应该非常熟悉了.在此过程中将检查表达式的类型,发现类型不正确的操作时就会报错.例如结构体之间无法用+ 进行加法运算,指针和数值之 ...

  9. C#高级知识点&(ABP框架理论学习高级篇)——白金版

    前言摘要 很早以前就有要写ABP高级系列教程的计划了,但是迟迟到现在这个高级理论系列才和大家见面.其实这篇博客很早就着手写了,只是楼主一直写写停停.看看下图,就知道这篇博客的生产日期了,谁知它的出厂日 ...

  10. SpringMVC的Action在同一时间里只允许同一个浏览器的单次进入?

    最近用SpringMVC写了一个很简单的测试程序,代码如下: @Controller public class LongTimeTaskController { @RequestMapping(val ...