转载请注明本文出自maplejaw的博客(http://blog.csdn.net/maplejaw_)
开源库地址:https://github.com/ReactiveX/RxJava
解读版本:1.1.8
基本概念
RxJava 是一个基于Java的响应式扩展实现: 即一个通过使用可观察序列来编写异步和基于事件的程序库。
它扩展了观察者模式以支持数据/事件序列,您可以根据声明好的规则通过操作符将序列组合在一起,而不用去担心低级别的线程,同步,线程安全和并发数据结构的各种问题。
基本用法
前面既然说了RxJava扩展了观察者模式,也就是说,RxJava是采用观察者模式实现的。既然是观察者模式,那么一定需要两个东西,被观察者和观察者。
怎么初始化一个观察者?(以下例子以订阅String类型为例子)
我们可以直接使用Observer
来初始化,Observer
是一个接口,里面有onNext
,onCompleted
,onError
三个抽象方法。
Observer<String> observer=new Observer<String>() {
@Override
public void onCompleted() {
//正常终止时调用,onError和onCompleted只会通知一个
}
@Override
public void onError(Throwable e) {
//当Observable遇到错误或者无法返回期望的数据时会调用这个方法,后续不会再调用onNext和onCompleted
}
@Override
public void onNext(String s) {
//Observable调用这个方法发射数据
}
};
此外我们可以使用Observer
的子类Subscriber
来初始化。Subscriber
相对于Observer
增加了onStart
和unsubscribe
,事实上,即使你使用的是Observer
,在内部仍然会被包装为Subscriber
。
Subscriber<String> subscriber=new Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
}
};
怎么初始化一个被观察者?
初始化被观察者使用Observable
,在call
内进行处理事件。可以看出call的参数为Subscriber
,这也进一步证实了Observer
会被包装为Subscriber
。只要被观察者调用call方法,订阅者就可以接受到事件/数据了。
Observable<String> observable=Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("hello");
subscriber.onNext("welcome to china");
subscriber.onCompleted();
}
});
那么问题来了,怎么建立一个订阅关系?
只需被观察者调用Observable.subscribe(Subscriber)
即可。
于是整个流程是这样的。
//被观察者
Observable<String> observable=Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("hello");
subscriber.onNext("welcome to china");
subscriber.onCompleted();
}
});
//观察者
Observer<String> observer=new Observer<String>() {
@Override
public void onCompleted() {
Log.d("JG","onCompleted");
}
@Override
public void onError(Throwable e) {
Log.d("JG","onError");
}
@Override
public void onNext(String s) {
Log.d("JG",s);
}
};
//被观察者订阅观察者(实际应理解为观察者订阅被观察者。)
observable.subscribe(observer);
运行结果如下。
此外,该库还有非常完善的异常捕获机制,当在处理数据时发生异常,可以自动捕获并回调到onError
中。将observable
修改成如下后,进行测试:
Observable<String> observable=Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
//...
throw new RuntimeException();//模拟抛出异常
}
});
测试结果如下:
OK,基本用法已经介绍完了,接下来,本篇将深入源码内部一探究竟(操作符相关内容将在下一篇单独介绍,如果只对操作符感兴趣敬请期待下篇)。如果你只是刚接触RxJava,请看给 Android 开发者的 RxJava 详解这篇文章。
源码解读
观察者(Subscriber)
Subscriber
提供了一种从被观察者接收推送数据和通知以及从被观察者中取消订阅的机制。
实现了Observer和Subscription接口,在Observer的基础上加入了onStart生命周期方法。该类属性如下:
public abstract class Subscriber<T> implements Observer<T>, Subscription {
private static final long NOT_SET = Long.MIN_VALUE;//未设置请求数量
private final SubscriptionList subscriptions;//订阅列表,一个存放订阅者(实现了Subscription接口)的列表,以便一同解除订阅
private final Subscriber<?> subscriber;//订阅者
private Producer producer;//生产者(用来处理反压),被观察和观察者之间的请求通道
private long requested = NOT_SET; //请求数, 默认为Long.MIN_VALUE。
protected Subscriber() {
this(null, false);
}
protected Subscriber(Subscriber<?> subscriber, boolean shareSubscriptions) {
this.subscriber = subscriber;
//是否共享订阅列表
this.subscriptions = shareSubscriptions && subscriber != null ? subscriber.subscriptions : new SubscriptionList();
}
//..
//省略了部分源码
}
从源码可以看出Subscriber
内部包含了一个子Subscriber
,可以共享同一个订阅列表。Producer用于建立被观察者和观察者间的可以指定请求数量的请求通道,一般用来配合解决反压问题(backpressure)。Producer是一个函数式接口,里面就一个抽象方法void request(long n);
。SubscriptionList
是一个订阅列表,以便将多个订阅者一起取消订阅。
关于设置Producer和请求数的源码如下:
request(long n)
protected final void request(long n) {
if (n < 0) {
//必须大于等于0
throw new IllegalArgumentException("number requested cannot be negative: " + n);
}
Producer producerToRequestFrom = null;
synchronized (this) {
if (producer != null) {
producerToRequestFrom = producer;
} else {
//没有producer的话就保存到Subscriber的requested值,会逐渐累加。
addToRequested(n);
return;
}
}
//如果有producer就直接调用Producer的request。
producerToRequestFrom.request(n);
}
setProducer
public void setProducer(Producer p) {
long toRequest;//请求数
boolean passToSubscriber = false;//是否传递给子Subscriber
synchronized (this) {
toRequest = requested;//赋值之前保存的请求数
producer = p;//赋值给producer
if (subscriber != null) {
//内部Subscriber不为空
if (toRequest == NOT_SET) {