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. .NET 4.6.2正式发布带来众多特性

    虽然大多数人的注意力都集中在.NET Core上,但与原来的.NET Framework相关的工作还在继续..NET Framework 4.6.2正式版已于近日发布,其重点是安全和WinForms/ ...

  2. 再讲IQueryable<T>,揭开表达式树的神秘面纱

    接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...

  3. InnoDB关键特性学习笔记

    插入缓存 Insert Buffer Insert Buffer是InnoDB存储引擎关键特性中最令人激动与兴奋的一个功能.不过这个名字可能会让人认为插入缓冲是缓冲池中的一个组成部分.其实不然,Inn ...

  4. 学习ASP.NET Core, 怎能不了解请求处理管道[3]: 自定义一个服务器感受一下管道是如何监听、接收和响应请求的

    我们在<服务器在管道中的"龙头"地位>中对ASP.NET Core默认提供的具有跨平台能力的KestrelServer进行了介绍,为了让读者朋友们对管道中的服务器具有更 ...

  5. 从display:run-in;中学习新技能

    有时我们想在一行内显示一个标题,以及一段内容,虽然看起来比较简单,但是为了语义化用dl比较合适,但是它默认是block元素,改成inline?那么有多段呢?不就都跑上来了?用float?那问题也挺多. ...

  6. Java compiler level does not match解决方法

    从别的地方导入一个项目的时候,经常会遇到eclipse/Myeclipse报Description  Resource Path Location Type Java compiler level d ...

  7. cocos2dx调用浏览器打开网址

    安卓端cocos2dx/platform/android路径下CCApplication.h: virtual void openURL(const char* pszUrl); CCApplicat ...

  8. Linux基础介绍【第二篇】

    远程连接Linux的原理 SHH远程连接介绍 当前,在几乎所有的互联网企业环境中,最常用的Linux提供远程连接服务的工具就是SSH软件,SSH分为SSH客户端和SSH服务端两部分.其中,SSH服务端 ...

  9. Java中的进程和线程

     Java中的进程与线程 一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是 ...

  10. java的poi技术读取Excel数据到MySQL

    这篇blog是介绍java中的poi技术读取Excel数据,然后保存到MySQL数据中. 你也可以在 : java的poi技术读取和导入Excel了解到写入Excel的方法信息 使用JXL技术可以在 ...