0.前言:
本文讨论是基于是rxJava2.+版本。
先来段helloRxJava,然后再阐述下各种概念。
库的引入:
compile ‘io.reactivex.rxjava2:rxjava:x.y.z’
具体版本号请参考github上最新的代码:Github
这个框架是一个线程可控的事件收发框架。并且提供了许多的操作符来适应各种场景来做这件事。它是采用的观察者模式。
1.Hello RxJava
1.1:Observer观察者,事件接收者。
Observer即观察者,根据观察者模式的思想,它是事件的接受方,所以它决定当收到事件的时候将有怎样的行为(数据处理)。
Observer<String> observer = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "subscribe");
}
@Override
public void onNext(Integer value) {
Log.d(TAG, "" + value);
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "error");
}
@Override
public void onComplete() {
Log.d(TAG, "complete");
}
};
1.2:Observable被观察者,事件发送者。
Observable即被观察者,根据观察者模式的思想,他既然是被观察的一方,那么它就决定了传达给观察者们的事件的时机和内容。
Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onComplete();
}
});
注意这里的Observable创建的方式.create()。
1.3:双方建立连接
observable.subscribe(observer);
只有简历连接之后,事件的收发端才开始工作。
建立连接之后的运行结果:
11-29 17:07:54.491 29573-29573/zj.playrxjava D/PlayRxJava: subscribe
11-29 17:07:54.491 29573-29573/zj.playrxjava D/PlayRxJava: 1
11-29 17:07:54.491 29573-29573/zj.playrxjava D/PlayRxJava: 2
11-29 17:07:54.491 29573-29573/zj.playrxjava D/PlayRxJava: 3
11-29 17:07:54.491 29573-29573/zj.playrxjava D/PlayRxJava: complete
1.4:合并代码,链式调用:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onComplete();
}
}).subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "subscribe");
}
@Override
public void onNext(Integer value) {
Log.d(TAG, "" + value);
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "error");
}
@Override
public void onComplete() {
Log.d(TAG, "complete");
}
});
3.事件模型
它的事件模型是一个队列结构,F1FO,先进先出。
也就是说,事件发送者Observerble先后发送三个事件A、B、C,那么事件接收者Observer收到的事件顺序同样为A、B、C。
基于此,RxJava提供了不同类型的事件流控制单元。这体现在代码里就是不同的方法,具备不同的属性,这些属性的不同会导致事件传输的结果不同。并且,同时作用于事件收发俩端。
它体现在事件发送端(Observable)时则是主动调的方法,它体现在事件接收端(Observer)时则是回调函数,类似如下代码:
Observable 发送端:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
}
})
Observer 接收端:
subscribe(new Observer<Integer>() {
......
@Override
public void onNext(Integer value) {
Log.d(TAG, "" + value);
}
......
}
那么下面来描述下这几个控制单元。
3.1.onNext
这个控制单元平淡无奇,就是事件发送端调一次(emitter.onNext(1)),事件接收端接收回调(onNext)一次,属于最基本的”事件发送”方法。
3.2.onComplete
当事件发送端发送了一个onComplete后, 事件发送端onComplete之后的事件将会继续发送, 而事件接收端收到onComplete事件之后将不再继续接收事件。
3.3.onError
这个跟上一个onComplete有点像。
我们来把上面的代码改成这样:
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
Log.e(TAG,"emitter.onNext(1)");
emitter.onNext(2);
Log.e(TAG,"emitter.onNext(2)");
emitter.onError(null);
Log.e(TAG,"emitter.onError(null)");
emitter.onNext(3);
Log.e(TAG,"emitter.onNext(3)");
emitter.onComplete();
Log.e(TAG,"eemitter.onComplete()");
}
接收端打出如下日志:
11-29 20:06:33.090 25658-25658/zj.playrxjava D/PlayRxJava: subscribe
11-29 20:06:33.091 25658-25658/zj.playrxjava D/PlayRxJava: 1
11-29 20:06:33.091 25658-25658/zj.playrxjava D/PlayRxJava: 2
11-29 20:06:33.093 25658-25658/zj.playrxjava D/PlayRxJava: error
发送端打出如下日志:
11-29 20:08:44.570 31771-31771/zj.playrxjava E/PlayRxJava: emitter.onNext(1)
11-29 20:08:44.570 31771-31771/zj.playrxjava E/PlayRxJava: emitter.onNext(2)
11-29 20:08:44.570 31771-31771/zj.playrxjava E/PlayRxJava: emitter.onError(null)
11-29 20:08:44.571 31771-31771/zj.playrxjava E/PlayRxJava: emitter.onNext(3)
11-29 20:08:44.571 31771-31771/zj.playrxjava E/PlayRxJava: eemitter.onComplete()
目前为止这个方法和onComplete是一样的,但是如果我们把代码改成这样程序就会崩溃,也就是说,onError事件是不能发送俩次的。
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
Log.e(TAG,"emitter.onNext(1)");
emitter.onNext(2);
Log.e(TAG,"emitter.onNext(2)");
emitter.onError(null);
Log.e(TAG,"emitter.onError(null)");
emitter.onError(null);
Log.e(TAG,"emitter.onError(null)");
emitter.onNext(3);
Log.e(TAG,"emitter.onNext(3)");
emitter.onComplete();
Log.e(TAG,"eemitter.onComplete()");
}
抛出如下异常:
11-29 20:11:07.014 6665-6665/zj.playrxjava E/AndroidRuntime: FATAL EXCEPTION: main
Process: zj.playrxjava, PID: 6665
java.lang.NullPointerException: onError called with null. Null values are generally not allowed in 2.x operators and sources.
at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.onError(ObservableCreate.java:74)
at zj.playrxjava.MainActivity$5.subscribe(MainActivity.java:134)
at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:40)
at io.reactivex.Observable.subscribe(Observable.java:10179)
at zj.playrxjava.MainActivity.baseUse(MainActivity.java:142)
at zj.playrxjava.MainActivity.onCreate(MainActivity.java:41)
at android.app.Activity.performCreate(Activity.java:6736)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2641)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2749)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1498)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:160)
at android.app.ActivityThread.main(ActivityThread.java:6197)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:874)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:764)
3.4.onSubscribe
这个方法比较特别相较于上面说那几个比较特别。
他是在订阅的时候(observable.subscribe(observer)),也就是observable调用subscribe的时候,observer这个方法进行回调,并且,注意这个并且比较重要,在observer回调方法public void onSubscribe(Disposable d)内的回调参数内有一个Disposable d,这就引入了下一个概念Disposable。
另外需要注意的是subscribe的多个重载方法:
【这里我转的一段Season_zlc大神的描述】
作者:Season_zlc
链接:http://www.jianshu.com/p/464fa025229e
public final Disposable subscribe() {}
public final Disposable subscribe(Consumer<? super T> onNext) {}
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) {}
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete) {}
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete, Consumer<? super Disposable> onSubscribe) {}
public final void subscribe(Observer<? super T> observer) {}
我们之前调用就是最后一个
public final void subscribe(Observer observer) {}。
这里着重说下其他几个:
- 不带任何参数的subscribe() 表示下游不关心任何事件,你上游尽管发你的数据去吧, 老子可不管你发什么.
- 带有一个Consumer参数的方法表示下游只关心onNext事件, 其他的事件我假装没看见, 因此我们如果只需要onNext事件可以这么写:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
Log.d(TAG, "emit 1");
emitter.onNext(1);
Log.d(TAG, "emit 2");
emitter.onNext(2);
Log.d(TAG, "emit 3");
emitter.onNext(3);
Log.d(TAG, "emit complete");
emitter.onComplete();
Log.d(TAG, "emit 4");
emitter.onNext(4);
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG, "onNext: " + integer);
}
});
- 其他几个方法同理, 这里就不一一解释了.
3.5.Disposable
这个Disposable对象是啥呢?
我们看他的代码就俩方法,dispose,isDisposed:
/**
* Represents a disposable resource.
*/
public interface Disposable {
/**
* Dispose the resource, the operation should be idempotent.
*/
void dispose();
/**
* Returns true if this resource has been disposed.
* @return true if this resource has been disposed
*/
boolean isDisposed();
}
这里我主要关注他的dispose()方法,这个方法也比较特殊,为什么说它特殊呢,它的作用是接收端单方面地切断事件接收流,所以它一般是在observer内进行调用,我们知道事件的发起都是在Observable内的,也就是说维持事件流动向一般都是发生在事件发送端,然而,正因为有它的存在,在事件接收端也具备了影响事件流传递的功能,但是,这只是事件接收端单方面的操作,也就是说,即便是在接收端停止了事件接收,在发送端却依然会按计划进行事件的发送,这也就类似于变向的收到了一个onComplete事件。
举个例子,如果我们将上面的代码修改了,在onSubscribe方法内进行一条d.dispose(),修改后的代码如下:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onComplete();
}
}).subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "subscribe");
d.dispose();
}
@Override
public void onNext(Integer value) {
Log.d(TAG, "" + value);
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "error");
}
@Override
public void onComplete() {
Log.d(TAG, "complete");
}
});
那么我们来看它的运行结果,肯定是除了onSubscribe()一条信息都接收不到的,我们看运行结果:
11-29 19:56:11.106 9792-9792/zj.playrxjava D/PlayRxJava: subscribe
通过结果可以看出,我们的推测没错。