RxJava不要重复使用(reuse)Subscriber的实例

时间:2022-12-16 15:56:36


如果你对RxJava1.x还不是了解,可以参考下面文章。

​​1. RxJava使用介绍​​ ​​【视频教程】​​​
​​​2. RxJava操作符​​​
  ​​• Creating Observables(Observable的创建操作符)​​ ​​【视频教程】​​​
  ​​• Transforming Observables(Observable的转换操作符)​​ ​​【视频教程】​​​
  ​​• Filtering Observables(Observable的过滤操作符)​​ ​​【视频教程】​​​
  ​​• Combining Observables(Observable的组合操作符)​​ ​​【视频教程】​​​
  ​​• Error Handling Operators(Observable的错误处理操作符)​​ ​​【视频教程】​​​
  ​​• Observable Utility Operators(Observable的辅助性操作符)​​ ​​【视频教程】​​​
  ​​• Conditional and Boolean Operators(Observable的条件和布尔操作符)​​ ​​【视频教程】​​​
  ​​• Mathematical and Aggregate Operators(Observable数学运算及聚合操作符)​​ ​​【视频教程】​​​
  ​​• 其他如observable.toList()、observable.connect()、observable.publish()等等;​​ ​​【视频教程】​​​
​​3. RxJava Observer与Subcriber的关系​​ ​​【视频教程】​​​
​​4. RxJava线程控制(Scheduler)​​ ​​【视频教程】​​​
​​5. RxJava 并发之数据流发射太快如何办(背压(Backpressure))​​ ​​【视频教程】​


RxJava不要重复使用(reuse)Subscriber的实例,如有重复使用的需要,请使用Observer代替。

在​​《RxJava Observer与Subscriber的关系》​​ 中,我们讲了Observer与Subscriber的关系,我们重点关注一下subscribe(mObserver)和subscribe(mSubscriber)执行结果的区别:

  • subscribe(mSubscriber)这种订阅方式在第二次请求数据时就不会执行了,原因就是onCompleted后自动取消了订阅
  • subscribe(mObserver)则不出现此问题。

今天我们进一步深入学习了解一下 Observer与Subscriber的区别。

先来看一个例子。

private static void test1() {
Observable observable = Observable.create(new Observable.OnSubscribe<String>(){
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hello RxJava");
subscriber.onCompleted();
}
});;
Subscriber subscriber = new Subscriber<String>() {
@Override
public void onCompleted() {
System.out.println("onCompleted");
}
@Override
public void onError(Throwable e) {
System.out.println("onError");
}
@Override
public void onNext(String value) {
System.out.println("onNext value : "+ value);
}
};

Subscription subscription = observable.subscribe(subscriber);
System.out.println("1.subscriber.isUnsubscribed() ? " + subscriber.isUnsubscribed());
System.out.println("1.subscription.isUnsubscribed() ? " + subscription.isUnsubscribed());
System.out.println("----------------");

observable.subscribe(subscriber);//重新建立订阅关系

System.out.println("*****************");

Observable.create(new Observable.OnSubscribe<String>(){
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Second");
subscriber.onCompleted();
}
}).subscribe(subscriber);
}

private static void test2() {
Observable observable = Observable.just("Hello RxJava");
Subscriber subscriber = new Subscriber<String>() {
@Override
public void onCompleted() {
System.out.println("onCompleted");
}
@Override
public void onError(Throwable e) {
System.out.println("onError");
}
@Override
public void onNext(String value) {
System.out.println("onNext value : "+ value);
}
};

Subscription subscription = observable.subscribe(subscriber);
System.out.println("2.subscriber.isUnsubscribed() ? " + subscriber.isUnsubscribed());
System.out.println("2.subscription.isUnsubscribed() ? " + subscription.isUnsubscribed());
System.out.println("----------------");

observable.subscribe(subscriber);

System.out.println("*****************");

Observable.create(new Observable.OnSubscribe<String>(){
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Second");
subscriber.onCompleted();
}
}).subscribe(subscriber);
}

test1方法运行结果如下:

onNext value : Hello RxJava
onCompleted
1.subscriber.isUnsubscribed() ? true
1.subscription.isUnsubscribed() ? true
----------------
onNext value : Hello RxJava
onCompleted
*****************
onNext value : Second
onCompleted

test2方法运行结果如下:

onNext value : Hello RxJava
onCompleted
2.subscriber.isUnsubscribed() ? true
2.subscription.isUnsubscribed() ? true
----------------
*****************
onNext value : Second
onCompleted

在文章的开头,我们提到“subscribe(mSubscriber)这种订阅方式在第二次请求数据时就不会执行了,原因就是onCompleted后自动取消了订阅 ”,看了上面test1方法的执行结果(subscribe(mSubscriber)可以重复订阅),是不是感觉这句话错了呢?test2方法执行结果正好符合我们总结的观点,那这个又是为什么呢?

经过查找资料,才发现原来是操作符导致的问题。

Observable.just

在使用Observable.just操作符创建Observable时,有如下代码:

public static <T> Observable<T> just(T t1, T t2) {
return from((T[])new Object[] { t1, t2 });
}

public static <T> Observable<T> from(T[] array) {
int n = array.length;
if (n == 0) {
return empty();
} else
if (n == 1) {
return just(array[0]);
}
return create(new OnSubscribeFromArray<T>(array));
}

public final class OnSubscribeFromArray<T> implements OnSubscribe<T> {
final T[] array;
public OnSubscribeFromArray(T[] array) {
this.array = array;
}

@Override
public void call(Subscriber<? super T> child) {
child.setProducer(new FromArrayProducer<T>(child, array));
}
......
}

最后在call被调用的时候会去执行setProducer()…这其中就会检查当前是否是isUnSubscribred(),如果isUnSubscribred()为true就不会执行onNext()、onCompleted()了。

综上所述当使用just(from操作符也类似)这种方式创建Observable时,当数据发射完成之后会执行onCompleted(),而这个方法中就会进行unsubscribe(),取消订阅,当取消了订阅就是不可逆的,所以以后每次发生事件都会因为判断是取消订阅了 所以无法再执行onNext()…;官方给出的建议是每次使用都new一个新的Subscriber 或者是使用Observer。

Observable.create

通过create创建的Observable 怎么就可以重复使用一个固定的Subscriber呢?其实并不复杂,因为我们重写了OnSubscribe中的call()方法,在里面直接去call onNext(),onCompleted();这样我们不会如上面一样去执行setProducer()…也就不会有去检查是否被取消订阅了。

今天讨论的内容在我在RxJava官方提了issues,有兴趣的也可以参考下:
​​​https://github.com/ReactiveX/RxJava/issues/5085​

subscribe(mObserver)和subscribe(mSubscriber)执行结果就会有区别:

  • mObserver可以重复使用,也就是subscribe(mObserver)可以重复订阅;
  • 当使用Observable.create方式创建Observable时,mSubscriber也能重复使用,也可以实现subscribe(mSubscriber)重复订阅,但当使用Observable.just、- Observable.from方式创建Observable时,mSubscriber不能重复使用,也就不能重复订阅了
  • RxJava给出的建议是每次使用都new一个新的Subscriber 或者是使用Observer,也就是不要重复使用mSubscriber。

最后以akarnokd的一句话做个总结:

Don’t reuse Subscriber; it is of no benefit if I evaluate what would each operator do with a reused Subscriber.