Rxjava cold/hot Observable

时间:2023-03-09 08:57:02
Rxjava cold/hot Observable

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取得一样的数据。