简单记录一些基础知识和使用方法,目标——简单!能用!
Github地址:
https://github.com/ReactiveX/RxJava
https://github.com/ReactiveX/RxAndroid
依赖库:
implementation 'io.reactivex.rxjava2:rxjava:2.2.2'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
使用场景:异步!
实现原理:观察者模式!
简单用:
Observable | 被观察者 |
Observer | 观察者 |
来个例子:
//创建被观察者
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) {
emitter.onNext("G1");
emitter.onNext("G2");
emitter.onComplete();
}
}).subscribe( new Observer<String>() {//创建观察者并订阅
private Disposable mDisposable;
@Override
public void onSubscribe(Disposable d) {
Log.v(TAG, "onSubscribe");
mDisposable = d;
}
@Override
public void onNext(String s) {
Log.v(TAG, "onNext:" + s);
if("ok".equals(s)) {
mDisposable.dispose();
}
}
@Override
public void onError(Throwable e) {
Log.v(TAG, "onError:" + e);
}
@Override
public void onComplete() {
Log.v(TAG, "onComplete");
}
});
被观察者Observable被创建后,可以通过ObservableEmitter发数据;
观察者Observer的接口中可以收到ObservableEmitter发送的数据;
方法有3个:
onNext:发送数据;
onError:发送错误消息;
onComplete:发送完成,调用之后再调用onNext观察者Observer也不会收到消息;
示例中的代码,运行后LOG如下:
V/x999x: onSubscribe
V/x999x: onNext:G1
V/x999x: onNext:G2
V/x999x: onComplete
观察者Observer的onSubscribe接口会最先被调用;而G3消息如预期一样,没有被送达;
onSubscribe接口中提供了一个Disposable对象,可以调用dispose方法中断消息发送;
修改subscribe方法代码如下:
emitter.onNext("G1");
emitter.onNext("ok");
emitter.onNext("G2");
emitter.onComplete();
emitter.onNext("G3");
再次运行后,LOG如下:
V/x999x: onSubscribe
V/x999x: onNext:G1
V/x999x: onNext:ok
调用dispose方法后,onNext和onComplete都不再执行;
最后再测试一下onError方法,修改subscribe方法代码如下:
emitter.onNext("G1");
emitter.onError(new Throwable("GOOD GAME!"));
emitter.onNext("ok");
emitter.onNext("G2");
emitter.onComplete();
emitter.onNext("G3");
再次运行后,LOG如下:
V/x999x: onSubscribe
V/x999x: onNext:G1
V/x999x: onError:java.lang.Throwable: GOOD GAME!
发送onError消息,onNext和onComplete都将不再发送;
这里需要提一点,在通过dispose中断消息后,在调用onError运行会报错!
所以调用onError消息前最好判断一下,修改subscribe方法代码如下:
emitter.onNext("G1");
emitter.onNext("ok");
if (!emitter.isDisposed()) {
emitter.onError(new Throwable("GOOD GAME!"));
}
emitter.onNext("G2");
emitter.onComplete();
emitter.onNext("G3");
上述代码,如果去掉isDisposed会直接运行报错!
定线程:
subscribeOn | 指定消息发送者(被观察者)的线程,只能指定一次,多次指定,只第一次起效 |
observeOn | 指定观察者的线程,可多次指定 |
来个例子:
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) {
Log.v(TAG, "Observable thread is : " + Thread.currentThread().getName());
emitter.onNext("Go Go Go");
emitter.onComplete();
}
}).subscribeOn(Schedulers.newThread())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.v(TAG, "Consumer mainThread is : " + Thread.currentThread().getName());
Log.v(TAG,"accept=" + s);
}
})
.observeOn(Schedulers.io())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.v(TAG, "Consumer io Thread is : " + Thread.currentThread().getName());
Log.v(TAG,"accept=" + s);
}
});
运行结果:
V/x999x: Observable thread is : RxNewThreadScheduler-1
V/x999x: Consumer mainThread is : main
V/x999x: accept=Go Go Go
V/x999x: Consumer io Thread is : RxCachedThreadScheduler-2
V/x999x: accept=Go Go Go
从例子中可以看到,观察者可以有多个;
观察者除了Observer之外还有一个简化的版本消费者——Consumer!
线程一共分为以下几种,根据需求可以选择:
AndroidSchedulers.mainThread() | 代表Android的主线程 |
Schedulers.newThread() | 代表一个常规的新线程 |
Schedulers.io() | 代表io操作的线程, 通常用于网络,读写文件等io密集型的操作 |
Schedulers.computation() | 代表CPU计算密集型的操作, 例如需要大量计算的操作 |
转数据:
map:当被观察者提供的数据和观察者使用的数据需要某种转换的时候可以用用它;个人感觉类似adapter,毕竟很多网络操作之类的返回的JSON数据,我们自己一般都要重新封装成对象的;
来个例子:
class Person{
String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "My name is " + name;
}
}
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) {
emitter.onNext("Liu Bei");
emitter.onNext("Guan Yu");
emitter.onNext("Zhang Fei");
}
}).map(new Function<String, Person>() {
@Override
public Person apply(String s) {
return new Person(s);
}
}).subscribe(new Consumer<Person>() {
@Override
public void accept(Person person) throws Exception {
Log.d(TAG, person.toString());
}
});
运行LOG如下:
2018-04D/x999x: My name is Liu Bei
D/x999x: My name is Guan Yu
D/x999x: My name is Zhang Fei
合数据:
zip:将两个被观察者的数据合二为一;这个东西实际使用中没试过;
数据配对是严格按照发射数据的顺序的;
如果双方数据长度不一致,按短的那个来;
举个例子:
Observable observable1 = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) {
emitter.onNext("Liu Bei");
emitter.onNext("Guan Yu");
emitter.onNext("Zhang Fei");
}
});
Observable observable2 = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) {
emitter.onNext("Da Ge");
emitter.onNext("Er Ge");
emitter.onNext("San Di");
emitter.onNext("Si Di");
}
});
Observable.zip(observable1, observable2, new BiFunction<String, String, String>() {
@Override
public String apply(String o, String o2) throws Exception {
return o + " is " + o2;
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String o) throws Exception {
Log.v(TAG, o);
}
});
运行后LOG:
V/x999x: Liu Bei is Da Ge
V/x999x: Guan Yu is Er Ge
V/x999x: Zhang Fei is San Di
无论运行多少次,刘备都是大哥,四弟也永远出不来!
Concat | 把两个发射器连接成一个发射器 |
just | 直接发送数据 |
take | 接受一个 long 型参数 count ,代表至多接收 count 个数据 |
timer | 定时任务 |
interval | 用于间隔时间执行某个操作,其接受三个参数,分别是第一次发送延迟,间隔时间,时间单位 |
buffer | 操作符接受两个参数,buffer(count,skip),作用是将 Observable 中的数据按 skip (步长) 分成最大不超过count的buffer ,然后生成一个Observable |
Filter | 过滤器,可以接受一个参数,让其过滤掉不符合我们条件的值 |
distinct | 去重复 |
FlatMap | 把一个发射器Observable通过某种方法转换为多个Observables,然后再把这些分散的Observables装进一个单一的发射器Observable。但有个需要注意的是,flatMap 并不能保证事件的顺序 |
concatMap | concatMap与FlatMap的唯一区别就是concatMap保证了顺序 |
Single/SingleObserver | Single只会接收一个参数,而SingleObserver只会调用onError()或者onSuccess() |
debounce | 去除发送频率过快的项 |
defer | 每次订阅都会创建一个新的Observable,并且如果没有被订阅,就不会产生新的Observable |
last | 仅取出可观察到的最后一个值,或者是满足某些条件的最后一项 |
merge | 把多个Observable结合起来,接受可变参数,也支持迭代器集合。它和concat的区别在于,不用等到 发射器 A 发送完所有的事件再进行发射器 B 的发送 |
reduce | 每次用一个方法处理一个值,可以有一个 seed 作为初始值 |
scan | 操作符作用和上面的 reduce 一致,唯一区别是 reduce 只追求结果,而 scan 会始终如一地把每一个步骤都输出。 |
window | 按照实际划分窗口,将数据发送给不同的 Observable |
背压式:
被观察者发送事件的速度大于观察者接收事件的速度时,观察者内会创建一个无限制大少的缓冲池存储未接收的事件,因此当存储的事件越来越多时就会导致OOM的出现
Flowable | 被观察者 |
Subscriber | 观察者 |
举个例子:
Flowable.create(new FlowableOnSubscribe<String>() {
@Override
public void subscribe(FlowableEmitter<String> emitter) throws Exception {
}
}, BackpressureStrategy.BUFFER)
.subscribe(new Subscriber<String>() {
@Override
public void onSubscribe(Subscription s) {
}
@Override
public void onNext(String s) {
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
});