本文篇幅较长 建议收藏起来等时间空闲详细阅读
本篇文章主要是一份学习笔记
RxJava是一个在java VM上可以使用可观测的序列来组成异步的,基于事件的程序库, RxJava是一个基于时间流.实现异步操作的库
实现异步 类似于android中的ASyncTask,Handler作用
基于事件流的链式调用,保持代码简洁&优雅
生活场景: 去吃饭.
角色 | 作用 | 类比 |
---|---|---|
被观察者Observable | 产生事件 | 顾客 |
观察者Observer | 接受事件,并作出相应动作 | 厨房 |
订阅者Subscribe | 连接被观察者&观察者 | 服务员 |
事件Event | 被观察者*观察者 沟通的载体 | 菜式 |
原理总结为被观察者通过订阅者按顺序发送事件给观察者,观察者按事件接受事件的顺序&做出对应的响应动作.
创建被观察者(Observable)并且产生事件
即顾客到饭店–>坐到位置–>点菜 具体实现;
// 1. 创建被观察者 Observable 对象
Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
// create() 是 RxJava 最基本的创造事件序列的方法
// 此处传入了一个 OnSubscribe 对象参数
// 当 Observable 被订阅时,OnSubscribe 的 call() 方法会自动被调用,即事件序列就会依照设定依次被触发
// 即观察者会依次调用对应事件的复写方法从而响应事件
// 从而实现被观察者调用了观察者的回调方法 & 由被观察者向观察者的事件传递,即观察者模式
// 2. 在复写的subscribe()里定义需要发送的事件
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
// 通过 ObservableEmitter类对象产生事件并通知观察者
// ObservableEmitter类介绍
// a. 定义:事件发射器
// b. 作用:定义需要发送的事件 & 向观察者发送事件
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onComplete();
}
});
<--扩展:RxJava 提供了其他方法用于 创建被观察者对象Observable -->
// 方法1:just(T...):直接将传入的参数依次发送出来
Observable observable = Observable.just("A", "B", "C");
// 将会依次调用:
// onNext("A");
// onNext("B");
// onNext("C");
// onCompleted();
// 方法2:from(T[]) / from(Iterable extends T>) : 将传入的数组 / Iterable 拆分成具体对象后,依次发送出来
String[] words = {"A", "B", "C"};
Observable observable = Observable.from(words);
// 将会依次调用:
// onNext("A");
// onNext("B");
// onNext("C");
// onCompleted();
创建观察者(Observer)并且定义响应事件行为
发生的事件类型包括 Next事件,complete事件,error事件
事件类型 | 定义 | 作用 | 使用规则 | 使用方法 |
---|---|---|---|---|
Next | 普通时间 | 向观察者发送需要响应事件的信号 | 被观察者可无限次的发送Next事件,观察者无限次接受事件 | onNext |
Complete | 事件队列完结,(事件) | 标志,被观察者,不在发送普通事件 | 1. 当被观察者发送了一个Complete事件后被观察者在complete事件后的事件将会继续发送,但是观察者收到complete事件后将不会再接受任何事件 2.被观察者可以不发送complete事件 |
onCompleted() |
error | 事件队列异常 (事件) | 标志 事件处理过程中出现异常 | 1. 当被观察者发送一个Error事件后,被观察者在error事件后的事件将会继续发送,但是观察者收到error事件后将不会继续接受任何事件 2.被观察者可以不发送Error事件 |
onErrror() |
在一个正确运行的事件序列中:onComplete和onError事件相互排斥,只能拥有唯一的一个事件.
具体实现:
<--方式1:采用Observer 接口 -->
// 1. 创建观察者 (Observer )对象
Observer<Integer> observer = new Observer<Integer>() {
// 2. 创建对象时通过对应复写对应事件方法 从而 响应对应事件
// 观察者接收事件前,默认最先调用复写 onSubscribe()
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "开始采用subscribe连接");
}
// 当被观察者生产Next事件 & 观察者接收到时,会调用该复写方法 进行响应
@Override
public void onNext(Integer value) {
Log.d(TAG, "对Next事件作出响应" + value);
}
// 当被观察者生产Error事件& 观察者接收到时,会调用该复写方法 进行响应
@Override
public void onError(Throwable e) {
Log.d(TAG, "对Error事件作出响应");
}
// 当被观察者生产Complete事件& 观察者接收到时,会调用该复写方法 进行响应
@Override
public void onComplete() {
Log.d(TAG, "对Complete事件作出响应");
}
};
<--方式2:采用Subscriber 抽象类 -->
// 说明:Subscriber类 = RxJava 内置的一个实现了 Observer 的抽象类,对 Observer 接口进行了扩展
// 1. 创建观察者 (Observer )对象
Subscriber<String> subscriber = new Subscriber<Integer>() {
// 2. 创建对象时通过对应复写对应事件方法 从而 响应对应事件
// 观察者接收事件前,默认最先调用复写 onSubscribe()
@Override
public void onSubscribe(Subscription s) {
Log.d(TAG, "开始采用subscribe连接");
}
// 当被观察者生产Next事件 & 观察者接收到时,会调用该复写方法 进行响应
@Override
public void onNext(Integer value) {
Log.d(TAG, "对Next事件作出响应" + value);
}
// 当被观察者生产Error事件& 观察者接收到时,会调用该复写方法 进行响应
@Override
public void onError(Throwable e) {
Log.d(TAG, "对Error事件作出响应");
}
// 当被观察者生产Complete事件& 观察者接收到时,会调用该复写方法 进行响应
@Override
public void onComplete() {
Log.d(TAG, "对Complete事件作出响应");
}
};
<--特别注意:2种方法的区别,即Subscriber 抽象类与Observer 接口的区别 -->
// 相同点:二者基本使用方式完全一致(实质上,在RxJava的 subscribe 过程中,Observer总是会先被转换成Subscriber再使用)
// 不同点:Subscriber抽象类对 Observer 接口进行了扩展,新增了两个方法:
// 1. onStart():在还未响应事件前调用,用于做一些初始化工作
// 2. unsubscribe():用于取消订阅。在该方法被调用后,观察者将不再接收 & 响应事件
// 调用该方法前,先使用 isUnsubscribed() 判断状态,确定被观察者Observable是否还持有观察者Subscriber的引用,如果引用不能及时释放,就会出现内存泄露
通过订阅者(subscribe)连接被观察者和观察者
即顾客点菜–>服务员下单到厨房–>厨房做菜
具体实现
observable.subscribe(observer)
//扩展说明
<-- Observable.subscribe(Subscriber) 的内部实现 -->
public Subscription subscribe(Subscriber subscriber) {
subscriber.onStart();
// 步骤1中 观察者 subscriber抽象类复写的方法,用于初始化工作
onSubscribe.call(subscriber);
// 通过该调用,从而回调观察者中的对应方法从而响应被观察者生产的事件
// 从而实现被观察者调用了观察者的回调方法 & 由被观察者向观察者的事件传递,即观察者模式
// 同时也看出:Observable只是生产事件,真正的发送事件是在它被订阅的时候,即当 subscribe() 方法执行时.
create()
作用: 完整创建一个被观察者(Observable),最基本的操作符
具体使用:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(3);
emitter.onNext(4);
emitter.onComplete();
}
}).subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
Log.e(TAG, "onSubscribe");
}
@Override
public void onNext(Integer integer) {
Log.e(TAG, "integer" + integer);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError");
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete");
}
});
//依次执行 onSubscribe-->integer1-->integer2-->integer3-->onComplete 如果那个步骤出错会执行onError
快速创建&&发送事件
just()
快速创建被观察者对象(observable),直接传入发送的事件,最多可发送10个事件
fromArray()
快速创建被观察者对象(observable),直接传入数组发送事件,只能传入数组,传入list默认为一个事件
fromltearable()
快速创建被观察对象(observable) 直接传入集合对象,
never()
不发送任何事件
empty()
该方法创建的被观察者对象发送事件的特点,仅仅执行Complete事件,直接通知完成
error()
延迟创建
defer()
直到观察者(observer)订阅时,才会动态创建被观察者对象(observable)&发送事件
通过observable工厂方法创建被观察者对象(observable)
每次订阅都会得到一个刚创建的最新的observable对象,这可以确保observable对象里的数据是最新的.
i = 20;//首次初始化
Observable<Integer> observable = Observable.defer(new Callable<ObservableSource<Integer>>() {
@Override
public ObservableSource<Integer> call() throws Exception {
return Observable.just(i); //执行i=20;
}
});
i = 30;//重新赋值
//订阅者订阅事件 得到log是 i=30,
observable.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
Log.e(TAG, "连接suber");
}
@Override
public void onNext(Integer integer) {
Log.e(TAG, integer + "");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Log.e(TAG, "完成整个流程..");
}
});
timer()
作用:快速创建一个被观察者对象(observable) 发送事件的特点:延迟指定时间后,发送一个数值0(Long类型)
本质: 延迟指定时间后,调用一次onNext()事件
interval()
快速创建一个被观察者observable,每隔指定时间就发送事件,
本质: 发送事件序列:=从0开始.无线递增1的整数序列
// 参数说明:
// 参数1 = 第1次延迟时间;
// 参数2 = 间隔时间数字;
// 参数3 = 时间单位;
Observable.interval(3,1,TimeUnit.SECONDS)
// 该例子发送的事件序列特点:延迟3s后发送事件,每隔1秒产生1个数字(从0开始递增1,无限个)
intervalRange()
每隔指定时间就发送事件,可以指定发送数据的数量
本质:类似interval() 但是可以指定发送的数据数量
// 参数说明:
// 参数1 = 事件序列起始点;
// 参数2 = 事件数量;
// 参数3 = 第1次事件延迟发送时间;
// 参数4 = 间隔时间数字;
// 参数5 = 时间单位
Observable.intervalRange(3,10,2, 1, TimeUnit.SECONDS)
//1. 从3开始,一共发送10个事件;
// 2. 第1次延迟2s发送,之后每隔2秒产生1个数字(从0开始递增1,无限个)但是仅仅发送10次
range()
连续发送多个事件类似于intervalRange,区别在于没有延迟
// 参数说明:
// 参数1 = 事件序列起始点;
// 参数2 = 事件数量;
// 注:若设置为负数,则会抛出异常
Observable.range(3,10)
// 该例子发送的事件序列特点:从3开始发送,每次发送事件递增1,一共发送10个事件
rangeLong()
类似于range区别在于该方法支持long类型
// 参数说明:
// 参数1 = 事件序列起始点;
// 参数2 = 事件数量;
// 注:若设置为负数,则会抛出异常
Observable.rangeLong(3L,10)
// 该例子发送的事件序列特点:从3L开始发送,每次发送事件递增1,一共发送10个事件
//执行interval的每隔三秒的轮询.
Observable.interval(3, TimeUnit.SECONDS).doOnNext(aLong -> {
//开始retrofit请求
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://fy.iciba.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();
API api = retrofit.create(API.class);
Observable<Model> request = api.getRange("Training request");
request.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Model>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Model model) {
model.toString();
Log.e(TAG, model.toString());
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}).subscribe(new Observer<Long>() {//观察者订阅事件 开始执行延迟事件
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Long aLong) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
对整个序列中的事件/整个事件进行加工处理(变换操作),使得其转换为不同的事件/整个事件序列
Map();
作用:对被观察者(observable)发送的每个事件都通过指定函数处理,从而变换为另外一种事件 即被观察者发送的时间转换为任意类型事件
引用场景:数据类型的转换
具体使用: 从整形转给字符串类型
Observable.create((ObservableOnSubscribe<Integer>) emitter -> {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}).map(integer ->
"使用 Map变换操作符 将事件" + integer + "的参数从 整型" + integer + " 变换成 字符串类型" + integer)
.subscribe(s -> Log.e(TAG, s));
//简化版的 subscribe(new observer)
//没有执行onCompelete和onError
FlatMap()
作用:将被观察者发送的时间序列进行拆分&单独转换,在合并成一个新的事件序列,最后在进行发送.
原理: 为事件序列中的每个事件都创建一个Observable对象;
将对每个原始事件转换后的新事件都放入到对应observable对象;
将新建的歌observable都合并到一个新建的,总的observable对象;
新建的,总的observable对象,将新合并的事件序列发送给观察者observer
新合并生成的事件序列是无序的,即与旧序列发送事件的序列无关
Observable.create((ObservableOnSubscribe<Integer>) emitter -> {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}).flatMap((Function<Integer, ObservableSource<String>>) integer -> {
List list = new ArrayList();
for (int i1 = 0; i1 < 3; i1++) {
list.add(i1);
}
return Observable.fromIterable(list);
}).subscribe(s -> {
Log.e(TAG, s);
});
ConcatMap()
类似于FloatMap 但是合并后的新事件序列是有序的,顺序和原来数据一致.
Observable.create((ObservableOnSubscribe<Integer>) emitter ->
emitter.onNext(1))
.concatMap((Function<Integer, ObservableSource<String>>) integer -> {
List list = new ArrayList();
for (int i1 = 0; i1 < 3; i1++) {
list.add(i1);
}
return Observable.fromIterable(list);
}).subscribe(s -> {
Log.e(TAG, s);
});
Buffer()
定期从观察者(Observable)需要大宋的事件中获取一定数量的事件,&放入到缓存区中,最终发送
应用场景: 缓存被观察者发送的事件,
Observable.just(1, 2, 3, 4, 5, 6, 7).buffer(3, 1).subscribe(new Observer<List<Integer>>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(List<Integer> integers) {
Log.e(TAG, "缓存区里的事件数量" + integers.size());
for (int i1 = 0; i1 < integers.size(); i1++) {
Log.e(TAG, "事件=:" + i1);
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://fy.iciba.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();
API api = retrofit.create(API.class);
Observable<Model> range = api.getRange();
Observable<Model> range2 = api.getRange2();
range.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.doOnNext(model ->
Log.e(TAG, model.toString())
).observeOn(Schedulers.io()).flatMap(model -> range2)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(model -> Log.e(TAG, model.toString()), throwable ->
Log.e(TAG, "登录失败"+throwable.getMessage())
);
12-17 03:04:01.434 4460-4460/com.yishion.demo_count E/RxJavaTranslation: Model{status=1, content=ContentBean{from='en-EU', to='zh-CN', out='登录个人信息', vendor='tencent', err_no=0}}
12-17 03:04:03.554 4460-4460/com.yishion.demo_count E/RxJavaTranslation: Model{status=1, content=ContentBean{from='en-EU', to='zh-CN', out='登记个人资料', vendor='tencent', err_no=0}}
该类型的操作符的作用=组合多个被观察者
作用: 组合多个被观察者一起发送数据,合并后按发送顺序串口执行(concat组合最多观察者数量为4/concatArray则是大于4个)
具体使用
Observable.concatArray(
Observable.just(1, 89),
Observable.just(2, 189),
Observable.just(3, 289),
Observable.just(4, 389),
Observable.just(5, 478)
).observeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(integer ->
Log.e(TAG, "接收到了事件" + integer)
);
作用: 组合多个被观察者一起发送数据,合并后按时间线并行执行
和concat的区别 同样是组合多个被观察者一起发送数据,单concat操作符合并后是发送顺序串口执行
具体使用:
Observable.concatArray(
Observable.intervalRange(0,5,1,1,TimeUnit.SECONDS),
Observable.intervalRange(6,5,1,1,TimeUnit.SECONDS),
Observable.just(1, 89),
Observable.just(2, 189),
Observable.just(3, 289),
Observable.just(4, 389),
Observable.just(5, 478)
).observeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(integer ->
Log.e(TAG, "接收到了事件" + integer)
);
若希望onError事件推迟到其他被观察者发送事件结束后才触发
Observable.concatArrayDelayError(Observable.create(emitter -> {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onError(new NullPointerException());
emitter.onNext(5);
emitter.onComplete();
}),Observable.just(5,8,9)).subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
Log.e(TAG,"接收到了事件"+integer);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "对Error事件作出响应");
}
@Override
public void onComplete() {
Log.e(TAG, "对Complete事件作出响应");
}
});
作用: 合并多个被观察者发送的事件,生成一个新的事件序列,并最终发送
Observable<Integer> observable = Observable.create((ObservableOnSubscribe<Integer>) emitter -> {
emitter.onNext(1);
Thread.sleep(1000);
emitter.onNext(2);
emitter.onNext(3);
emitter.onComplete();
}).subscribeOn(Schedulers.io());
Observable<String> observable2 = Observable.create((ObservableOnSubscribe<String>) emitter -> {
emitter.onNext("A");
emitter.onNext("B");
emitter.onNext("C");
emitter.onNext("E");
emitter.onComplete();
}).subscribeOn(Schedulers.newThread());
Observable.zip(observable, observable2, (integer, s) -> integer + s)
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
Log.e(TAG, s);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, e.getMessage());
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete");
}
});
方法一 merge时间序列上合并
Observable<String> observable = Observable.just("网络请求");
Observable<String> observable1 = Observable.just("本地缓存");
Observable.merge(observable, observable1).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
Log.d(TAG, "数据源有: " + s);
result += s + "+";
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "对Error事件作出响应");
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete" + result);
}
});
zip合并
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://fy.iciba.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();
API aip = retrofit.create(API.class);
Observable<Model> observable = aip.getRange().subscribeOn(Schedulers.io());
Observable<Model> observable1 = aip.getRange2().subscribeOn(Schedulers.io());
Observable.zip(observable, observable1, (model, model2) -> model.toString() + model2.toString())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
Log.d(TAG, "合并后的数据为: "+s);
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "合并出错: "+e.getMessage());
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete");
}
});
//subscribeOn改变了调用前序列所运行的线程。
//observeOn 对调用之前的序列默不关心,也不会要求之前的序列运行在指定的线程上 对之前的序列产生的结果先缓存起来,然后再在指定的线程上,推送给最终的subscriber
String meayCache = null;
String diskCache = "我是磁盘数据";
Observable<String> observable = Observable.create(emitter -> {
if (meayCache != null) {
emitter.onNext(meayCache);
} else {
emitter.onComplete();
}
});
Observable<String> observable1 = Observable.create(emitter -> {
if (diskCache != null) {
emitter.onNext(diskCache);
} else {
emitter.onComplete();
}
});
Observable<String> observable2 = Observable.just("网络请求");
Observable.concat(observable, observable1, observable2).firstElement().subscribe(s ->
Log.d(TAG, "数据源来自于...:" + s),
throwable -> Log.e(TAG, throwable.getMessage())
);
// 2. 通过firstElement(),从串联队列中取出并发送第1个有效事件(Next事件),即依次判断检查memory、disk、network
// a. firstElement()取出第1个事件 = memory,即先判断内存缓存中有无数据缓存;由于memoryCache = null,即内存缓存中无数据,所以发送结束事件(视为无效事件)
// b. firstElement()继续取出第2个事件 = disk,即判断磁盘缓存中有无数据缓存:由于diskCache ≠ null,即磁盘缓存中有数据,所以发送Next事件(有效事件)
// c. 即firstElement()已发出第1个有效事件(disk事件),所以停止判断。
//给每个edittext设置被观察者,用于发送监听 使用rxBinding
Observable<CharSequence> nameObservable = RxTextView.textChanges(edName).skip(1);
Observable<CharSequence> ageObservable = RxTextView.textChanges(edAge).skip(1);
Observable<CharSequence> sexObservable = RxTextView.textChanges(edSex).skip(1);
//通过combinelatest()合并事件&联合判断
Observable.combineLatest(nameObservable, ageObservable, sexObservable,
(charSequence, charSequence2, charSequence3) -> {
boolean isNameValid = !TextUtils.isEmpty(edName.getText());
boolean isAgeValid = !TextUtils.isEmpty(edAge.getText());
boolean isSexValid = !TextUtils.isEmpty(edSex.getText());
Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
boolean isAgeNumber = pattern.matcher(edAge.getText()).matches();
return isNameValid & isAgeValid & isSexValid & isAgeNumber;
}).subscribe(aBoolean -> {
Log.e("admin", "提交按钮是否可点击" + aBoolean);
btnSub.setEnabled(true);
}, throwable ->
Log.e("admin", "出现错误" + throwable.getMessage())
);