引言
相信网上关于Rxjava的文章数不胜数,但是我不知道初学者有没有跟我一样觉得好迷茫,似懂非懂的样子真的很让人崩溃,对于我而言,要学一个东西,我就要真真正正把它给学会,学懂,所以我一定要弄懂RxJava是怎样运行的,只有弄懂它是怎样跑起来的,咱们后面才知道怎么写代码,怎么用好它,so,在这里我并不是告诉你怎么去用Rxjava,因为我也是刚学,但是我决定一步步来,把每天的学习记录下来。这里先讲的是Rxjava是怎么让观察者与被观察之间联系以及怎么运行的。
来,进入正题:
Rxjava我习惯叫它为观察者模式的变种,在设计模式中,观察者模式有两重要角色:观察者跟被观察者。
那么在Rxjava中同样也是有观察者跟被观察两个角色,那么这两个角色是怎么联系起来的。为了解答这个问答,我们先普及一个小小的东西:
在Rxjava中:
被观察者:Observable
观察者:Observer或者Subscriber
那么这两个角色是啥,作为程序员哪能不进去看看代码呢,源码是认识它们的最便捷的方式,来了:
(1)先看Observable
public class Observable<T> {
final OnSubscribe<T> onSubscribe;
/**
* Creates an Observable with a Function to execute when it is subscribed to.
* <p>
* <em>Note:</em> Use {@link #create(OnSubscribe)} to create an Observable, instead of this constructor,
* unless you specifically have a need for inheritance.
*
* @param f
* {@link OnSubscribe} to be executed when {@link #subscribe(Subscriber)} is called
*/
protected Observable(OnSubscribe<T> f) {
this.onSubscribe = f;
}
public static <T> Observable<T> create(OnSubscribe<T> f) {
return new Observable<T>(RxJavaHooks.onCreate(f));
}
/**
* Invoked when Observable.subscribe is called.
* @param <T> the output value type
*/
public interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
// cover for generics insanity
}
/**
* A one-argument action.
* @param <T> the first argument type
*/
public interface Action1<T> extends Action {
void call(T t);
}
可以看到Observable类中,OnSubscribe是它的唯一属性,从代码可以看出OnSubscribe是继承Action1,从本质上来说,跟Action1是一样的接口,只不过是专门用于Observable内部而已。从Observable类的源码上可以知道,这个类的实例化是通过这个方法构建的:
public static <T> Observable<T> create(OnSubscribe<T> f) {
return new Observable<T>(RxJavaHooks.onCreate(f));
}
可以看到OnSubscribe是Observable构造函数中必须唯一传入的参数,也就是说,只要创建了Observable。那么内部也一定有一个OnSubscribe对象,而OnSubscribe其实就是一个Action1接口,会回调call(T t)方法。当然Observable也可以通过简化的just()跟from()方法来创建。
(2)来看观察者:
Observer跟Subscriber是啥
public interface Observer<T> {
/**
* Notifies the Observer that the {@link Observable} has finished sending push-based notifications.
* <p>
* The {@link Observable} will not call this method if it calls {@link #onError}.
*/
void onCompleted();
/**
* Notifies the Observer that the {@link Observable} has experienced an error condition.
* <p>
* If the {@link Observable} calls this method, it will not thereafter call {@link #onNext} or
* {@link #onCompleted}.
*
* @param e
* the exception encountered by the Observable
*/
void onError(Throwable e);
/**
* Provides the Observer with a new item to observe.
* <p>
* The {@link Observable} may call this method 0 or more times.
* <p>
* The {@code Observable} will not call this method again after it calls either {@link #onCompleted} or
* {@link #onError}.
*
* @param t
* the item emitted by the Observable
*/
void onNext(T t);
}
public abstract class Subscriber<T> implements Observer<T>, Subscription {
// represents requested not set yet
private static final long NOT_SET = Long.MIN_VALUE;
private final SubscriptionList subscriptions;
private final Subscriber<?> subscriber;
/* protected by `this` */
private Producer producer;
/* protected by `this` */
private long requested = NOT_SET; // default to not set
protected Subscriber() {
this(null, false);
}
从源码上可以知道Observer其实就是一个接口,而Subscriber是Observer的实现类。
所以创建观察者从Observer跟Subscribe都可以,但是我们还是比较更倾向于用他的实现类。
(3)订阅
被观察者跟观察者都创建后,他们是怎么联系的,废话少说,谁不知道
Observable.subscribe(Subscriber)
那么调用subscribe()方法发生了什么,来,继续
public final Subscription subscribe(Subscriber<? super T> subscriber) {
return Observable.subscribe(subscriber, this);
}
static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> 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<T>(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) {
// special handling for certain Throwable/Error/Exception types
Exceptions.throwIfFatal(e);
// in case the subscriber can't listen to exceptions anymore
if (subscriber.isUnsubscribed()) {
RxJavaHooks.onError(RxJavaHooks.onObservableError(e));
} else {
// if an unhandled error occurs executing the onSubscribe we will propagate it
try {
subscriber.onError(RxJavaHooks.onObservableError(e));
} catch (Throwable e2) {
Exceptions.throwIfFatal(e2);
// if this happens it means the onError itself failed (perhaps an invalid function implementation)
// so we are unable to propagate the error correctly and will just throw
RuntimeException r = new OnErrorFailedException("Error occurred attempting to subscribe [" + e.getMessage() + "] and then again while trying to pass to onError.", e2);
// TODO could the hook be the cause of the error in the on error handling.
RxJavaHooks.onObservableError(r);
// TODO why aren't we throwing the hook's return value.
throw r; // NOPMD
}
}
return Subscriptions.unsubscribed();
}
}
public class SafeSubscriber<T> extends Subscriber<T> {
private final Subscriber<? super T> actual;
boolean done;
public SafeSubscriber(Subscriber<? super T> actual) {
super(actual);
this.actual = actual;
}
/**
* Notifies the Subscriber that the {@code Observable} has finished sending push-based notifications.
* <p>
* The {@code Observable} will not call this method if it calls {@link #onError}.
*/
@Override
public void onCompleted() {
if (!done) {
done = true;
try {
actual.onCompleted();
} catch (Throwable e) {
// we handle here instead of another method so we don't add stacks to the frame
// which can prevent it from being able to handle StackOverflow
Exceptions.throwIfFatal(e);
RxJavaHooks.onError(e);
throw new OnCompletedFailedException(e.getMessage(), e);
} finally { // NOPMD
try {
// Similarly to onError if failure occurs in unsubscribe then Rx contract is broken
// and we throw an UnsubscribeFailureException.
unsubscribe();
} catch (Throwable e) {
RxJavaHooks.onError(e);
throw new UnsubscribeFailedException(e.getMessage(), e);
}
}
}
}
/**
* Notifies the Subscriber that the {@code Observable} has experienced an error condition.
* <p>
* If the {@code Observable} calls this method, it will not thereafter call {@link #onNext} or
* {@link #onCompleted}.
*
* @param e
* the exception encountered by the Observable
*/
@Override
public void onError(Throwable e) {
// we handle here instead of another method so we don't add stacks to the frame
// which can prevent it from being able to handle StackOverflow
Exceptions.throwIfFatal(e);
if (!done) {
done = true;
_onError(e);
}
}
/**
* Provides the Subscriber with a new item to observe.
* <p>
* The {@code Observable} may call this method 0 or more times.
* <p>
* The {@code Observable} will not call this method again after it calls either {@link #onCompleted} or
* {@link #onError}.
*
* @param args
* the item emitted by the Observable
*/
@Override
public void onNext(T args) {
try {
if (!done) {
actual.onNext(args);
}
} catch (Throwable e) {
// we handle here instead of another method so we don't add stacks to the frame
// which can prevent it from being able to handle StackOverflow
Exceptions.throwOrReport(e, this);
}
}
/**
* The logic for {@code onError} without the {@code isFinished} check so it can be called from within
* {@code onCompleted}.
*
* @see <a href="https://github.com/ReactiveX/RxJava/issues/630">the report of this bug</a>
*/
@SuppressWarnings("deprecation")
protected void _onError(Throwable e) { // NOPMD
RxJavaPlugins.getInstance().getErrorHandler().handleError(e);
try {
actual.onError(e);
} catch (OnErrorNotImplementedException e2) { // NOPMD
/*
* onError isn't implemented so throw
*
* https://github.com/ReactiveX/RxJava/issues/198
*
* Rx Design Guidelines 5.2
*
* "when calling the Subscribe method that only has an onNext argument, the OnError behavior
* will be to rethrow the exception on the thread that the message comes out from the observable
* sequence. The OnCompleted behavior in this case is to do nothing."
*/
try {
unsubscribe();
} catch (Throwable unsubscribeException) {
RxJavaHooks.onError(unsubscribeException);
throw new OnErrorNotImplementedException("Observer.onError not implemented and error while unsubscribing.", new CompositeException(Arrays.asList(e, unsubscribeException))); // NOPMD
}
throw e2;
} catch (Throwable e2) {
/*
* throw since the Rx contract is broken if onError failed
*
* https://github.com/ReactiveX/RxJava/issues/198
*/
RxJavaHooks.onError(e2);
try {
unsubscribe();
} catch (Throwable unsubscribeException) {
RxJavaHooks.onError(unsubscribeException);
throw new OnErrorFailedException("Error occurred when trying to propagate error to Observer.onError and during unsubscription.", new CompositeException(Arrays.asList(e, e2, unsubscribeException)));
}
throw new OnErrorFailedException("Error occurred when trying to propagate error to Observer.onError", new CompositeException(Arrays.asList(e, e2)));
}
// if we did not throw above we will unsubscribe here, if onError failed then unsubscribe happens in the catch
try {
unsubscribe();
} catch (Throwable unsubscribeException) {
RxJavaHooks.onError(unsubscribeException);
throw new OnErrorFailedException(unsubscribeException);
}
}
/**
* Returns the {@link Subscriber} underlying this {@code SafeSubscriber}.
*
* @return the {@link Subscriber} that was used to create this {@code SafeSubscriber}
*/
public Subscriber<? super T> getActual() {
return actual;
}
}
也就是开启了观察者,new 出一个SafeSubscriber,也就是继承Subscriber,实现其各个方法回调。
也就是开始回调onNext,onCompleted等等。
例子说明
private void start() {
//创建被观察者
Observable observable=createObservable();
//创建观察者
Subscriber subscriber=createSubscriber();
mText.append("开始订阅,准备观察...\n");
//事实上,observable不止可以订阅subscriber,也可以订阅ActionX()
observable.subscribe(subscriber);
//就像现在这样
// observable.subscribe(new Action1<String>() {
// @Override
// public void call(String s) {
// //Action1也就意味着,只能传入一个参数 ----> String s,同理Action0,Action2....,
// //在这个call方法中传入了onNext()的参数,相当于代替了onNext方法,但是就不能监听onComplete,onError方法了
// mText.append("执行观察者中的onNext()...\n");
// mText.append(s+"...\n");
// }
// });
}
private Subscriber createSubscriber() {
//创建观察者
Subscriber subscriber=new Subscriber<String>() {
@Override
public void onCompleted() {
mText.append("执行观察者中的onCompleted()...\n");
mText.append("订阅完毕,结束观察...\n");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
mText.append("执行观察者中的onNext()...\n");
mText.append(s+"...\n");
}
};
return subscriber;
}
private Observable createObservable(){
//创建被观察者,这是最正常的创建方法
Observable observable=Observable.create(new Observable.OnSubscribe<String>(){
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("一二三四五");
subscriber.onNext("上山打老虎");
subscriber.onNext("老虎一发威");
subscriber.onNext("武松就发怵");
subscriber.onCompleted();
}
});
//想要图方便,可以这样创建
//from(T[])
// String [] kk={"一二三四五","上山打老虎","老虎一发威","武松就发怵"};
// Observable observable=Observable.from(kk);
//或者这样
//just(T...)
// Observable observable=Observable.just("一二三四五","上山打老虎","老虎一发威","武松就发怵");
return observable;
}
}
根据上面的运行原理可知,当出发start()方法后,会先创建被观察者Observable,然后在创建观察者Subscriber,接着会调用 observable.subscribe(subscriber);
这样子后,会进入到
private Observable createObservable(){
//创建被观察者,这是最正常的创建方法
Observable observable=Observable.create(new Observable.OnSubscribe<String>(){
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("一二三四五");
subscriber.onNext("上山打老虎");
subscriber.onNext("老虎一发威");
subscriber.onNext("武松就发怵");
subscriber.onCompleted();
}
});
这里面的call()方法回调,上面已经说了,订阅subscribe会先走OnSubscribe的call()方法。然后再回调subscriber的各个回调。