[]RxJava
RxJava是一个实现处理异步操作的库, 比AsyncTask 和Handler处理异步操作都要简洁(逻辑简洁)。
[]RxJava的原理简析
RxJava 的异步实现,是通过一种扩展的观察者模式来实现的。观察者不需要时刻监听被观察者,而是采用注册或者称为订阅的方式,告诉被观察者:我需要你的某种状态,你要在状态变化的时候通知我。
RxJava 有四个基本概念:Observable (被观察者), Observer (观察者),subscribe (订阅),事件。被观察者(Observable)和观察者(Observer)通过subscribe()实现订阅关系,从而Observable可以在需要的时候发出事件来通知Observer。
[]观察者(Observer)
观察者决定事件触发的时候将有怎样的行为。
Observer的实现方式
Observer<String> observer = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
除了Observer接口实现之外,Subscriber接口也能实现。
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onSubscribe(Subscription s) {
//执行请求
s.request(Long.MAX_VALUE);
}
@Override
public void onNext(String s) {
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
};
onSubscribe(Disposable d)或者onSubscribe(Subscription s):事件还未发送之前被调用,可以用于做一些准备工作。参数d可用于取消订阅,参数s可用于请求数据(如果不调用请求,Subscriber的onNext()与onComplete()不会被调用)或者取消订阅。
onComplete():事件队列完结。RxJava不仅把每个事件单独处理,还会把它们看做一个队列。RxJava规定,当不会再有新的onNext()发出时,需要触发onComplete()作为标志。
onError():事件队列异常。在事件处理过程中出异常时,onError()会被触发,同时队列自动终止,不允许再有事件发出。
一个正确运行的事件序列中, onComplete()和onError()有且只有一个,并且是事件序列中的最后一个。
需要注意的是,onComplete()和onError()二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。
[]被观察者(Observable)
被观察者决定什么时候触发事件以及触发怎样的事件。
Observable的实现方式
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("hello");
e.onNext("hi");
e.onNext("ye");
e.onComplete();
}
});
除了Observable接口实现之外,Flowable抽象类也能实现。
Flowable<String> flowable = Flowable.create(new FlowableOnSubscribe<String>() {
@Override
public void subscribe(FlowableEmitter<String> e) throws Exception {
e.onNext("hello");
e.onNext("hi");
e.onNext("ye");
e.onComplete();
}
//需要指定背压策略
}, BackpressureStrategy.BUFFER);
当被观察者被订阅的时候,subscribe()会自动被调用,事件序列就会依照设定依次触发(会被调用三次onNext()和一次onComplete())。这样,由被观察者调用了观察者的回调方法,就实现了由被观察者向观察者的事件传递,即观察者模式。
RxJava 还提供了其它快捷方式来创建事件队列。
just():将传入的参数依次发送出来。
Observable<String> observable = Observable.just("hello", "hi", "ye");
// 将会依次调用
// onNext("Hello");
// onNext("Hi");
// onNext("ye");
// onCompleted();
fromArray():传入的数组拆分成具体对象后,依次发送出来。
String[] items = {"Hello", "Hi", "ye"};
Observable<String> observable = Observable.fromArray(items);
// 将会依次调用
// onNext("Hello");
// onNext("Hi");
// onNext("ye");
// onCompleted();
还有fromIterable()等等。
[]订阅(Subscribe)
Subscribe的实现方式
observable.subscribe(observer); 或者
flowable.subscribe(subscriber);
Observeable用于订阅Observer,是不支持背压,而Flowable用于订阅Subscriber,是支持背压(Backpressure)。
背压:是指在异步场景中,被观察者发送事件速度远快于观察者的处理速度的情况下,一种告诉上游的被观察者降低发送速度的策略。没有背压可能会导致MissingBackpressureException。
使用Observable/Observer的时候,需要考虑的是,数据量是不是很大(官方给出以1000个事件为分界线,仅供各位参考)。
subscribe() 还支持不完整定义的回调。RxJava会自动根据定义创建出 Observer。
不完整回调的实现方式:
Consumer nextConsumer = new Consumer() {
@Override
public void accept(@NonNull Object o) throws Exception {
}
};
Consumer errConsumer = new Consumer() {
@Override
public void accept(@NonNull Object o) throws Exception {
}
};
Action completeAction = new Action() {
@Override
public void run() throws Exception {
}
};
// 自动创建Observer,并使用nextConsumer,errConsumer和completeAction
来定义onNext(),onError()和onCompleted()
observable.subscribe(nextConsumer, errConsumer, completeAction);
[]调度器(Scheduler)——线程控制
在不指定线程的情况下, RxJava遵循的是线程不变的原则,即在哪个线程调用subscribe(),就在哪个线程生产事件;在哪个线程生产事件,就在哪个线程消费事件。如果需要切换线程,就需要用到Scheduler。
Scheduler:相当于线程控制器,RxJava通过它来指定每一段代码应该运行在什么样的线程。
RxJava提供的Scheduler
Schedulers.newThread():启用新线程来执行操作。
Schedulers.io():I/O 操作(读写文件,读写数据库,网络信息交互等)使用的Scheduler。它的内部是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下io() 比newThread()更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。
Schedulers.computation():计算使用的Scheduler。这个计算指的是 CPU密集型计算,即不会被 I/O等操作限制性能的操作,例如图形的计算。这个 Scheduler使用固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在computation()中,否则 I/O 操作的等待时间会浪费 CPU。
AndroidSchedulers.mainThread():Android指定在主线程进行操作。
使用subscribeOn()和observeOn()来对线程进行控制。
subscribeOn():指定subscribe()发生的线程,Observable运行在的线程,或者叫做事件产生的线程。
observeOn():指定Observer运行在的线程。或者叫做事件消费的线程。
Observable.just(1, 2, 3, 4, 5, 6)
//指定subscribe()发生在IO线程
.subscribeOn(Schedulers.io())
//指定Observer的回调发生在主线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer) throws Exception {
}
});
多次切换线程:observeOn()的多次调用
observeOn()指定的是Observer的线程,而这个Observer并不是subscribe() 参数中的Observer,而是observeOn() 执行时的当前Observable所对应的 Observer,即它的直接下级Observer。简单的来说,observeOn() 指定的是它之后的操作所在的线程。
因此在每个想要切换线程的位置调用一次observeOn()就可多次切换线程。
Observable.just("1", "2", "3", "4") //IO线程,由subscribeOn()指定
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.map(function) //新线程,由observeOn()指定
.observeOn(Schedulers.io())
.map(function) //IO线程,由observeOn()指定
.observeOn(AndroidSchedulers.mainThread())
.subscribe(consumer); //Android主线程,由observeOn()指定
subscribeOn() 的位置放在哪里都可以,但它是只能调用一次的。
Observable对象的doOnSubscribe():
是在subscribe()调用后并且在事件发送前执行,默认情况下,doOnSubscribe()执行在subscribe()发生的线程,而如果在doOnSubscribe()之后有subscribeOn(),它将执行在离它最近的subscribeOn()所指定的线程。
Observable.just("1", "2", "3", "4")
.subscribeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(consumer)//新线程,由subscribeOn()指定
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.io())
.subscribe(consumer);
[]变换操作
变换:就是将事件序列中的对象或整个序列进行加工处理,转换成不同的事件或事件序列。
map():事件对象的直接变换并返回。用于一对一的转化。
Observable.just("logo.png") //输入类型String
.map(new Function<String, Bitmap>() {
@Override
public Bitmap apply(@NonNull String s) throws Exception {//参数类型String 返回类型Bitmap
return null;
}
}).subscribe(new Consumer<Bitmap>() {
@Override
public void accept(@NonNull Bitmap bitmap) throws Exception { //参数类型位为Bitmap
}
});
map()将参数中的String转换成一个Bitmap后返回,而经过map()后,事件的参数类型也由String转为了Bitmap。
flatMap():用于一对多的转化。 也常用于嵌套的异步操作。
Observable.fromIterable(stuList)
.flatMap(new Function<Student, ObservableSource<Course>>() {
@Override
public ObservableSource<Course> apply(@NonNull Student student) throws Exception {
return Observable.fromIterable(student.getCourseList());
}
})
.subscribe(new Consumer<Course>() {
@Override
public void accept(@NonNull Course course) throws Exception {
}
});
flatMap()和map()都是把传入的参数转化之后返回另一个对象。但是flatMap() 中返回的是个ObservableSource,并且这个ObservableSource并不是被直接发送到了Observer的回调方法中。
flatMap()的原理
- 使用传入的事件对象创建一个ObservableSource。
- 并不发送这个ObservableSource,而是将它激活,于是它开始发送事件。
每一个创建出来的ObservableSource发送的事件,都被汇入同一个 Observable,而这个Observable负责将这些事件统一交给Observer的回调方法。
RxJava 还提供很多便捷的方法来实现事件序列的变换。
flatMapIterable(Function mapper):
switchMap(Function mapper):
scan(BiFunction accumulator):
[]过滤操作
filter(Predicate predicate):过滤不满足条件的值。
take(long count):获取前面的count个对象。
takeLast(int count):获取后面的count个对象。
skip(long count):忽略前面的count个对象。
skipLast(int count):忽略后面的count个对象。
elementAt(long index):获取第index的对象。
distinct(Function keySelector):过滤掉重复的值。
first(T defaultItem):获取第一个对象。
last(T defaultItem):获取最后一个对象。
[]组合操作
相关文章
给 Android 开发者的 RxJava 详解
http://gank.io/post/560e15be2dca930e00da1083#toc_30
RxJava系列
https://zhuanlan.zhihu.com/p/20687178
ReactiveX/RxJava文档中文版
https://mcxiaoke.gitbooks.io/rxdocs/content/