RxJava
Rxjava 介绍
RxJava是ReactiveX(反应性扩展)的Java VM实现:一个库,用于使用可观察序列组合异步和基于事件的程序。
RxJava 起步
Gradle 集成
compile 'io.reactivex.rxjava2:rxjava:2.2.0'
RxJava 的使用
先看一个简单demo:
相关代码如下:
public class RxJavaUse {
public static String TAG = RxJavaUse.class.getSimpleName();
public static void hello(String... args){
Disposable subscribe = Flowable.fromArray(args).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i(TAG, "accept:Hello "+ s);
}
});
}
}
执行调用:
RxJavaUse.hello(new String[]{"RxJava","is","Used"});
结果输出
2019-06-29 10:05:06.785 5158-5158/com.union.rxjava I/RxJavaUse: accept:Hello RxJava
2019-06-29 10:05:06.785 5158-5158/com.union.rxjava I/RxJavaUse: accept:Hello is
2019-06-29 10:05:06.786 5158-5158/com.union.rxjava I/RxJavaUse: accept:Hello Use
创建被观察者:
创建一个被观察者,你可以使用create() 方法,你也可以根据已有的数据去创建
1、根据已有的数据创建被观察者
使用 just(),from 方法 转换对象
public static void createObservable(){
String data [] = {"this","is","RxJava","demo"};
Observable<ArrayList> just = Observable.just(new ArrayList());
Observable<String[]> dataArray = Observable.just(data);
Observable<String> stringObservable = Observable.fromArray();
}
2、create()方法创建被观察者
demo1、
public static void createObservableByNone(){
Observable<String> objectObservable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("hello");
emitter.onNext("World");
}
});
objectObservable.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i(TAG, "accept:Hello "+ s);
}
});
}
方法调用:
RxJavaUse.createObservableByNone();
输出结果:
2019-06-29 11:01:18.905 23009-23009/com.union.rxjava I/RxJavaUse: accept:Hello hello
2019-06-29 11:01:18.906 23009-23009/com.union.rxjava I/RxJavaUse: accept:Hello World
demo2:
public static void createObservableByNone(){
Observable<String> objectObservable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("hello");
emitter.onNext("World");
}
});
objectObservable.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
Log.i(TAG, "onNext "+ s);
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onError "+ e.getMessage());
}
@Override
public void onComplete() {
Log.i(TAG, "onComplete ");
}
});
}
方法调用:
RxJavaUse.createObservableByNone();
输出结果:
2019-06-29 11:03:06.931 23871-23871/com.union.rxjava I/RxJavaUse: onNext hello
2019-06-29 11:03:06.931 23871-23871/com.union.rxjava I/RxJavaUse: onNext World
3、使用操作符
skip(10)跳过前 10 条
take(5) 获取下五条数据
map 进行数据变换
public static void createObservableSkip(){
Observable<String> stringObservable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("value1");
emitter.onNext("value2");
emitter.onNext("value3");
emitter.onNext("value4");
emitter.onNext("value5");
emitter.onNext("value6");
emitter.onNext("value7");
emitter.onNext("value8");
emitter.onNext("value9");
emitter.onNext("value10");
emitter.onNext("value11");
emitter.onNext("value12");
emitter.onNext("value13");
emitter.onNext("value14");
emitter.onNext("value15");
emitter.onNext("value16");
emitter.onNext("value17");
}
});
stringObservable.skip(10).take(5).map(new Function<String, String>() {
@Override
public String apply(String s) throws Exception {
return s+"skip_take";
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.i(TAG, "onSubscribe");
}
@Override
public void onNext(String s) {
Log.i(TAG, "onNext "+ s);
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onError "+ e.getMessage());
}
@Override
public void onComplete() {
Log.i(TAG, "onComplete");
}
});
}
方法调用:
RxJavaUse.createObservableSkip();
结果输出:
2019-06-29 11:14:42.474 7359-7359/com.union.rxjava I/RxJavaUse: onSubscribe
2019-06-29 11:14:42.474 7359-7359/com.union.rxjava I/RxJavaUse: onNext value11skip_take
2019-06-29 11:14:42.474 7359-7359/com.union.rxjava I/RxJavaUse: onNext value12skip_take
2019-06-29 11:14:42.475 7359-7359/com.union.rxjava I/RxJavaUse: onNext value13skip_take
2019-06-29 11:14:42.475 7359-7359/com.union.rxjava I/RxJavaUse: onNext value14skip_take
2019-06-29 11:14:42.475 7359-7359/com.union.rxjava I/RxJavaUse: onNext value15skip_take
2019-06-29 11:14:42.475 7359-7359/com.union.rxjava I/RxJavaUse: onComplete
响应流(Reactive Streams + RxJava)
响应流是一项协作工作,旨在标准化JVM上异步流的协议。RxJava团队从一开始就是工作的一部分,并支持使用响应流api,最终支持Java 9流api,这是响应流工作成功的结果。
RxJava 2。x将直接针对Java 8+的反应流api。该计划还将支持Java 9 j.u.c。在使用RxJava 2时,通过利用新的Java多版本jar来支持流类型。x在Java 9中,同时还在Java 8中工作。
RxJava 2将真正成为“反应性扩展”,因为现在有一个接口需要扩展。RxJava 1没有要扩展的基本接口或契约,因此必须从头定义它。RxJava 2的目标是成为高性能、经过战斗测试的轻量级(对响应流的单一依赖)、响应流和j.u.c的非自定义实现。流,它提供具有参数化并发性的高阶函数库。
Rx1转换响应流代码:
public abstract class RxReactiveStreams {
abstract <T> Publisher<T> toPublisher(Observable<T> observable) ;
abstract <T> Observable<T> toObservable(Publisher<T> publisher);
}
反应流和流发布器接口不提供任何操作符的实现,比如flatMap、merge、filter、take、zip和许多其他用于组合和转换异步流的操作符。发布者只能订阅。需要像RxJava这样的具体实现来提供组合。
RxJava和Akka Streams一直是十分优秀的响应流实现库。
Rx2:响应流代码:
public io.reactivex.Observable getValue(String key);
Scheduler
用来切换线程
demo:
public static void scheduler(){
Observable.create(new ObservableOnSubscribe<Object>() {
@Override
public void subscribe(ObservableEmitter<Object> emitter) throws Exception {
emitter.onNext("hello");
Log.i(TAG, " subscribe -ThreadName "+ Thread.currentThread().getName());
}
}).subscribeOn(Schedulers.newThread()).doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
Log.i(TAG, "accept - ThreadName "+ Thread.currentThread().getName());
}
}).subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
Log.i(TAG, "ThreadName "+ Thread.currentThread().getName());
}
});
}
控制台输出结果:
2019-07-01 10:27:25.776 27711-27711/com.union.rxjava I/RxJavaUse: accept - ThreadName main
2019-07-01 10:27:25.779 27711-27753/com.union.rxjava I/RxJavaUse: ThreadName RxNewThreadScheduler-1
2019-07-01 10:27:25.779 27711-27753/com.union.rxjava I/RxJavaUse: subscribe -ThreadName RxNewThreadScheduler-1
Subject
Subject可以看成是一个桥梁或者代理,在某些ReactiveX实现中(如RxJava),它同时充当了Observer和Observable的角色。因为它是一个Observer,它可以订阅一个或多个Observable;又因为它是一个Observable,它可以转发它收到(Observe)的数据,也可以发射新的数据。
由于一个Subject订阅一个Observable,它可以触发这个Observable开始发射数据(如果那个Observable是”冷”的–就是说,它等待有订阅才开始发射数据)。因此有这样的效果,Subject可以把原来那个”冷”的Observable变成”热”的。
Subject的种类
针对不同的场景一共有四种类型的Subject。他们并不是在所有的实现中全部都存在,而且一些实现使用其它的命名约定(例如,在RxScala中Subject被称作PublishSubject)
1、AsyncSubject
一个AsyncSubject只在原始Observable完成后,发射来自原始Observable的最后一个值。(如果原始Observable没有发射任何值,AsyncObject也不发射任何值)它会把这最后一个值发射给任何后续的观察者。
然而,如果原始的Observable因为发生了错误而终止,AsyncSubject将不会发射任何数据,只是简单的向前传递这个错误通知。
2、BehaviorSubject
当观察者订阅BehaviorSubject时
- 它开始发射订阅原始Observable前,发射的最后一个数据(如果此时还没有收到任何数据,它会发射一个默认值),
- 然后继续发射任何来自原始Observable的数据。
然而,如果原始的Observable因为发生了一个错误而终止,BehaviorSubject将不会发射任何数据,只是简单的向前传递这个错误通知。
3、PublishSubject
PublishSubject只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者。需要注意的是,PublishSubject可能会一创建完成就立刻开始发射数据(除非你可以阻止它发生),因此这里有一个风险:在Subject被创建后到有观察者订阅它之前这个时间段内,一个或多个数据可能会丢失。如果要确保来自原始Observable的所有数据都被分发,你需要这样做:或者使用Create创建那个Observable以便手动给它引入”冷”Observable的行为(当所有观察者都已经订阅时才开始发射数据),或者改用ReplaySubject。
如果原始的Observable因为发生了一个错误而终止,PublishSubject将不会发射任何数据,只是简单的向前传递这个错误通知。
4、ReplaySubject
ReplaySubject会发射所有来自原始Observable的数据给观察者,无论它们是何时订阅的。也有其它版本的ReplaySubject,在重放缓存增长到一定大小的时候或过了一段时间后会丢弃旧的数据(原始Observable发射的
如果你把ReplaySubject当作一个观察者使用,注意不要从多个线程中调用它的onNext方法(包括其它的on系列方法),这可能导致同时(非顺序)调用,这会违反Observable协议,给Subject的结果增加了不确定性。
RxJava的对应类
假设你有一个Subject,你想把它传递给其它的代理或者暴露它的Subscriber接口,你可以调用它的asObservable方法,这个方法返回一个Observable。具体使用方法可以参考Javadoc文档。
串行化
如果你把 Subject 当作一个 Subscriber 使用,注意不要从多个线程中调用它的onNext方法(包括其它的on系列方法),这可能导致同时(非顺序)调用,这会违反Observable协议,给Subject的结果增加了不确定性。
要避免此类问题,你可以将 Subject 转换为一个 SerializedSubject ,类似于这样:
mySafeSubject = new SerializedSubject( myUnsafeSubject );