最近有点时间来简单研究一下Rxjava原理,Rxjava基于传统的观察者模式,同样的在Rxjava观察者模式中有两个重要的角色:Observable(被观察者)、Observer(观察者)。当被观察者的数据或者状态发生改变的时候,会及时的告知观察者,而这个告知的过程就是一个订阅关系,在Rxjava中,Observable中提供subscribe方法来实现Observable和Observe的订阅关系。
Observer是一个接口,它提供了三个函数onComplete、onError、onNext。
- onComplete表示整个事件队列完结
- onError表示在事件队列处理的过程中发生了异常,并且在Observer的定义中,onComplete和onError是互斥,两者只会在同一时间调用一次
- onNext为观察者提供需要处理的事件
在平时Rxjava的使用中,我们通常不会直接去new这个Observer,而是使用它实现类Subscriber,从它的名字一目了然表示订阅者,即需要知道最终结果的那个角色。在Subscriber类定义中,它不仅实现了Observer接口,还实现了Subscription接口,它可以用来取消订阅关系,终止事件发送。
既然订阅者需要去订阅某一个事件,那这个事件是如何创建出来的?这个事件的创建是由Observeable(被观察者)创建的,它来处理这个事件整个过程最终将结果回调给Subscriber。
所以可以看出在整个Rxjava中有这么四个角色:Observable、Subscriber、subscribe(订阅关系)、事件。
通过简单的事例来了解这个过程:
Observable.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber super String> subscriber) {
StringBuilder builder = new StringBuilder();
builder.append("Rx");
builder.append("Java");
subscriber.onNext(builder.toString());
subscriber.onCompleted();
}
}).subscribe(new Subscriber() {
@Override
public void onCompleted() {
Log.i("TAG","onCompleted");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
Log.i("TAG","==> "+s);
}
});
这是一个简单的用例,这里没有涉及到线程切换、事件变换等复杂的使用。从代码中看到,Observable中提供了一个create函数:
public static Observable create(OnSubscribe f) {
return new Observable(RxJavaHooks.onCreate(f));
}
在create的函数中接受一个OnSubscribe对象,这个OnSubscribe是定义在Observable中的一个接口:
public interface OnSubscribe<T> extends Action1<Subscriber super T>> {
// cover for generics insanity
}
继承了Action1,在Action1申明了一个函数call,call函数接受一个泛型T
public interface Action1<T> extends Action {
void call(T t);
}
OnSubscribe指定了Action1中的泛型为Subscriber,所以call函数会接受一个Subscriber,那么这个Subscriber是怎么传递进来的,接着上面的事例继续跟踪源码,刚刚说到create函数里传递进来一个OnSubscribe对象,并且将这个对象作为参数传递到Observable的构造器中,在Observable的构造器中只做了一件事情:
protected Observable(OnSubscribe f) {
this.onSubscribe = f;
}
将外部new出来的OnSubscribe对象赋值给全局变量,至此准备工作已经做完了,在这里我觉得可以把OnSubscribe的call函数理解为被观察者要处理的事件,等到事件处理完之后需要将结果回调给Subscriber,所以在call函数中我们需要接受这一个Subscriber,调用它的onNext、onComplete、或者onError。
那么整个订阅的事件过程是通过subscribe函数展开的:
public final Subscription subscribe(Subscriber super T> subscriber) {
return Observable.subscribe(subscriber, this);
}
static Subscription subscribe(Subscriber super T> subscriber, Observable observable) {
// validate and proceed
if (subscriber == null) {
throw new IllegalArgumentException("subscriber can not be null");
}
if (observable.onSubscribe == null) {
throw new IllegalStateException("onSubscribe function can not be null.");
/*
* the subscribe function can also be overridden but generally that's not the appropriate approach
* so I won't mention that in the exception
*/
}
// new Subscriber so onStart it
subscriber.onStart();
/*
* See https://github.com/ReactiveX/RxJava/issues/216 for discussion on "Guideline 6.4: Protect calls
* to user code from within an Observer"
*/
// if not already wrapped
if (!(subscriber instanceof SafeSubscriber)) {
// assign to `observer` so we return the protected version
subscriber = new SafeSubscriber(subscriber);
}
// The code below is exactly the same an unsafeSubscribe but not used because it would
// add a significant depth to already huge call stacks.
try {
// allow the hook to intercept and/or decorate
RxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber);
return RxJavaHooks.onObservableReturn(subscriber);
} catch (Throwable e) {
...
}
}
在订阅关系中我们需要指明一个订阅者Subscriber,接着调用了Observable中的静态subscribe方法,在所有事件发送之前,它先调用了subscriber的onStart方法,用于做一些准备工作,然后对subscriber进行一次包装,跳过RxJavaHook的操作,先不去了解它的作用,最后可以看到它调用了Observable中之前赋值的全局变量OnSubscribe的call方法,并且将最后包装的subscriber传递进去,所以在上面的用例代码中,call函数创建一个新的String然后将这个结果通过subscriber的onNext传递过去即表示我们想要的最终结果。这个过程简单不复杂,我觉得先弄清楚基本的流程在去深入是个比较好的方法,只是我自己的见解,因为从一开始直接上来了解复杂的操作符和线程调度,会看的云里雨雾的。
再举一个常用的例子:
Observable.just("Tom","Bob","Json")
.subscribe(new Subscriber() {
@Override
public void onCompleted() {
Log.i(TAG,"onCompleted ");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
Log.i(TAG,"item = "+s);
}
});
just函数会把这3个item转换成一个Observable并将它们一一发送出去,也就是说onNext方法会调用3次,等到最后所有的事件发送完了调用onComplete来结束这个事件队列。
public static Observable just(T t1, T t2, T t3) {
return from((T[])new Object[] { t1, t2, t3 });
}
public static Observable from(T[] array) {
int n = array.length;
if (n == 0) {
return empty();
} else
if (n == 1) {
return just(array[0]);
}
return create(new OnSubscribeFromArray(array));
}
在just函数中将所有要发送的事件都存放在一个Object数组中并将这个数组传递给from,因为这里我们的length为3,所以直接调用了create方法,前面的用例1我们自己手动的去创建了一个OnSubscribe对象,在这里Rxjava帮我们创建了一个内置的OnSubscribe,可以肯定的一点就是这个OnSubscribeFromArray它是OnSubscribe的实现类,并且将它的实例对象赋值给Observable的全局变量OnSubscribe。
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(child, array));
}
//....
}
到这里同用例1一样我们的准备工作已经做完了,剩下的只是要知道是哪个订阅者需要订阅整个事件,那还是subscriber方法里传递一个Subscriber对象,同样的在subscribe方法里先是调用了onStart方法,然后调用Observable.OnSubscribe的call函数,这里的OnSubscribe就是OnSubscribeFromArray。回想到用例1的call函数里我们是自己创建一个事件然后自己手动的将结果回调给subscriber,那么在OnSubscribeFromArray的call函数中,我们并没有看到subscriber的任何回调函数,那么它是如何将事件发送出去的呢?这话说的如同放屁一般,那肯定是有办法的。
在call函数中看到有setProducer,这个Producer它是也是一个接口,官方给它的定义是:
Interface that establishes a request-channel between an Observable and a Subscriber and allows the Subscriber to request a certain amount of items from the Observable
意思就是说它用来在Observable和Subscriber之间建立一个请求通道,允许Subscriber主动的从Observable中请求一定量的item事件。也就是说整个事件发送的过程是有Producer来完成的。在Producer中只定义了一个方法:
public interface Producer {
/**
* Request a certain maximum number of items from this Producer. This is a way of requesting backpressure.
* To disable backpressure, pass {@code Long.MAX_VALUE} to this method.
*
* Requests are additive but if a sequence of requests totals more than {@code Long.MAX_VALUE} then
* {@code Long.MAX_VALUE} requests will be actioned and the extras may be ignored. Arriving at
* {@code Long.MAX_VALUE} by addition of requests cannot be assumed to disable backpressure. For example,
* the code below may result in {@code Long.MAX_VALUE} requests being actioned only.
*
*
* request(100);
* request(Long.MAX_VALUE-1);
*
*
* @param n the maximum number of items you want this Producer to produce, or {@code Long.MAX_VALUE} if you
* want the Producer to produce items at its own pace
* @throws IllegalArgumentException if the request amount is negative
*/
void request(long n);
}
从注释中知道n表示的是发送事件队列的大小长度,最大为Long.MAX_VALUE,如果超出这个长度的话系统会自动抛出一个非法参数异常。
既然它是接口那么肯定有实现类,在OnSubscribeFromArray中定义了一个FromArrayProducer静态内部类,它实现了Producer。在call函数中会调用subscriber的setProducer方法:
public void setProducer(Producer p) {
long toRequest;
boolean passToSubscriber = false;
synchronized (this) {
toRequest = requested;
producer = p;
if (subscriber != null) {
// middle operator ... we pass through unless a request has been made
if (toRequest == NOT_SET) {
// we pass through to the next producer as nothing has been requested
passToSubscriber = true;
}
}
}
// do after releasing lock
if (passToSubscriber) {
subscriber.setProducer(producer);
} else {
// we execute the request with whatever has been requested (or Long.MAX_VALUE)
if (toRequest == NOT_SET) {
producer.request(Long.MAX_VALUE);
} else {
producer.request(toRequest);
}
}
}
这个方法不太好理解,但是最终toRequest == NOT_SET 随之调用了producer.request(Long.MAX_VALUE);也就是在call函数中setProducer的时候就调用了request方法,转过头来看FromArrayProducer的request方法:
@Override
public void request(long n) {
if (n < 0) {
throw new IllegalArgumentException("n >= 0 required but it was " + n);
}
if (n == Long.MAX_VALUE) {
if (BackpressureUtils.getAndAddRequest(this, n) == 0) {
fastPath();
}
} else
if (n != 0) {
if (BackpressureUtils.getAndAddRequest(this, n) == 0) {
slowPath(n);
}
}
}
以为n从上面传递进来的是Long.MAX_VALUE所以进入到了fastPath方法中:
void fastPath() {
final Subscriber super T> child = this.child;
for (T t : array) {
if (child.isUnsubscribed()) {
return;
}
child.onNext(t);
}
if (child.isUnsubscribed()) {
return;
}
child.onCompleted();
}
从FromArrayProducer的构造器中我们知道child指向Subscriber,array指向了之前的Object数组,所以可以很清楚地看到在fastPath中它for循环迭代了array,判断subscriber是否取消订阅了,如果没有就调用了subscriber的onNext方法,这里的onNext调用了3次,最后调用了onComplete结束。
抛开Rxjava的复杂的事件变换和线程切换等操作,我们可以看到观察者模式在Rxjava中的体现的还是比较的清晰,但是仅仅了解这么一点还是不够的,因为Rxjava的精髓并不在这里。这篇文章只是简单了解一下它的流程是怎么进行的。