Android框架-RxJava

转载

定义

RxJava 是一个 基于事件流、实现异步操作的库

优点

逻辑简洁、实现优雅、使用简单
随着程序逻辑的复杂性提高,它依然能够保持简洁 & 优雅

原理

1)RxJava 原理 基于 一种扩展的 观察者模式

4个角色,相互关系:

角色作用类比
被观察者(Observable)产生事件顾客
观察者(Observer)接收事件,并给出响应动作厨房
订阅(Subscribe)连接 被观察者 & 观察者服务员
事件(Event)被观察者 & 观察者 沟通的载体菜式

被观察者 (Observable) 通过 订阅(Subscribe) 按顺序发送事件 给观察者 (Observer),
观察者(Observer) 按顺序接收事件 & 作出对应的响应动作。

RxJava1.0 与 2.0对比
区别ObservableFlowable
版本实现RxJava 1.0就存在RxJava2.0才有
角色订阅关系对应观察者 Observer对应观察者 Subscriber
功能Observable在 1.0 支持背压 (效果不好)
1、手动减少Observable发送的事件
2、延迟的方式降低 Observable 发射速度

Observable 在 2.0开始,不支持背压
Flowable 所有操作符强制支持背压
应用场景小数据流传输
默认缓存大小 = 16
大数据流传输
默认缓存大小 = 128
观察者创建方式
创建方式实现说明
创建 Observer 对象
new Observer<T>()观察者接收事件前,最先调用 onSubscribe()
创建 Subscriber 对象new Subscriber<T>()Subscriber类 是 RxJava 内置实现了 Observer 的抽象类
比 Observer 增加了 onStart() unsubscribe()两个方法
onStart():响应事件前调用
unsubscribe():用于取消订阅。 在该方法被调用后,观察者将不再接收 & 响应事件
调用该方法前,先使用 isUnsubscribed() 判断状态
确定被观察者 Observable 是否还持有观察者 Subscriber 的引用,
如果引用不能及时释放,就会出现内存泄露
Action、BiConsumer、BiFunction
Cancellable、Consumer、Function
Function3…
Consumer 每次接收到事件都会调用 Consumer # accept()

订阅:连接观察者、被观察者
observable.subscribe(observer) 或者 observable.subscribe(subscriber)

订阅方法说明说明2
Observable # subscribe()观察者不对任何事件做出响应被观察者可以发送
Observable # subscribe(Consumer<? super T> onNext)观察者只对 Next事件 作出响应参数表示观察者响应的事件类型
subscribe(Observer<? super T> observer)观察者对任何事件都作出响应

调用顺序
观察者.onSubscribe() > 被观察者.subscribe() > 观察者.onNext() > 观察者.onComplete()

取消订阅

Disposable.dispose() 切断观察者 与 被观察者 之间的连接
观察者订阅回调函数 onSubscribe(Disposable d) 中,获取 Disposable 引用
在观察者 onNext() 中,按需要执行 Disposable # dispose()

创建被观察者Observable
创建方式说明
Observable.create(ObservableOnSubscribe)在 subscribe(ObservableEmitter emitter) 定义发射事件
ObservableEmitter 事件发射器
if (!observer.isUnsubscribed()) {// 没有观察者时,Observable停止发射
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}
emitter.onComplete();
Observable.just(1, 2, 3,4)创建 被观察者对象(Observable) 只能 发送10个以下事件
Observable.fromArray(items)参数为 数组
如果传一个 list 集合进去,会把 list 当做一个数据元素发送
场景:10 个以上数组形式事件  或者 数组遍历
Observable.fromIterable(list)发送 传入的集合 List 数据
场景: 发送10个以上事件(集合形式)  或者 集合元素遍历
Observable.empty()仅发送 Complete 事件,观察者接收后会直接调用 onCompleted()
Observable.error(new RuntimeException())仅发送 Error事件,可自定义异常,观察者接收后会直接调用onError()
Observable.never()不发送任何事件, 观察者接收后什么都不调用
Observable.defer()延迟到 有观察者(Observer) 订阅时,才动态创建 Observable & 发送事件
场景:动态创建 Observable & 获取最新的 Observable 对象数据
Observable.timer(2, TimeUnit.SECONDS)延迟指定时间后,调用一次 onNext(0)
延迟指定时间,发送一个0 (Long类型),一般用于检测
timer()操作符默认运行在一个新线程上
自定义线程调度器(第3个参数):timer(long, TimeUnit, Scheduler)
Observable.interval(3 , 1 , TimeUnit.SECONDS)
参数1 = 第1次延迟时间;
参数2 = 间隔时间数字;
参数3 = 时间单位
每隔指定时间 就发送 事件
发送的事件序列 = 从0开始、无限递增 1 的整数序列

interval() 默认在 computation 调度器上执行
可指定线程调度器(第3个参数):interval(long, TimeUnit, Scheduler)
Observable.intervalRange(3 ,10 , 2, 1, TimeUnit.SECONDS)
参数1 = 事件序列起始点;
参数2 = 事件数量;
参数3 = 第1次事件延迟发送时间;
参数4 = 间隔时间数字;
参数5 = 时间单位
每隔指定时间 就发送从 0开始、无限递增1 的整数序列
可指定发送的数据的数量
Observable.range(3 ,10)
参数1 = 事件序列起始点;
参数2 = 事件数量;
若设置为负数,则会抛出异常
无延迟,连续发送 1 个每次递增 1 的整数事件序列,可指定范围
Observable.rangeLong(…)类似 range(),区别在于 该操作符支持数据类型 = Long
RxJava变换操作符
操作符说明使用
map()将 Observable 发送的事件,转换为任意的类型事件
场景:数据类型转换
observable.map(new Function<Integer, String>())
使用 Function 函数对事件进行统一变换
观察者接收到的是 变换后的事件
flatMap()将 Observable 发送的事件进行 拆分 & 单独转换,再合并成一个新的事件序列,最后再进行发送
场景:无序的将 Observable 的整个事件序列进行变换
步骤:
1.为每个事件都创建一个 Observable 对象
2.每个 原始事件 转换成 新事件,放入到对应 Observable 对象
3.将新建的每个 Observable 都合并到一个新建的、总的 Observable 对象
4.新的、总的 Observable 对象,将 新合并的事件序列,发送给观察者
observable.flatMap(new Function<Integer, ObservableSource<String>>())

Integer 每个原始事件转成 String 类型,放入 Observable
多个Observable 合并成一个总的Observable对象,发送给观察者
flatMap 事件转换是无序的
concatMap()作用类似flatMap()操作符
与flatMap()区别:新的 Observable 事件序列 的顺序 == 原始 Observable 事件序列的顺序
场景:有序的 将 Observable 发送的整个事件序列进行转换
.concatMap(new Function<Integer, ObservableSource<String>>())
buffer(3, 1)
设置缓存区大小 & 步长
参数一:缓存区大小 = 每次从Observable 获取的事件数量
参数二:步长 = 每次向右偏移步长
从 Obervable 事件序列中,
获取一定数量的事件 放到缓存,发送整个缓存的事件
然后,向右偏移一定步长,继续获取缓存并发送
Observable.just(1, 2, 3, 4, 5)
.buffer(3, 1)
.subscribe(…)
每次从 Observable 获取 3个 事件
每次发射缓存事件后,向右偏移的 1 步
第一次获取 1、2、3,第二次获取2、3、4,…
RxJava组合、合并操作符
操作符说明使用
concat()组合 <= 4 个 Observable,按发送顺序,串行执行
concatArray()组合 > 4 个 Observable,按发送顺序,串行执行
merge()组合 <= 4 个 Observable,按时间线,并行执行Observable.merge(
// 从0开始、发送3个数据、间隔时间 1s,每次递增1
Observable.intervalRange(0, 3, 1, 1, TimeUnit.SECONDS),
// 从2开始、发送3个数据、间隔时间 1s,每次递增1
Observable.intervalRange(2, 3, 1, 1, TimeUnit.SECONDS)
)
.subscribe(…)
结果:两个被观察者发送事件并行执行
输出结果 = 0,2 -> 1,3 -> 2,4
mergeArray()组合 > 4 个 Observable,按时间线,并行执行
concatDelayError()、mergeDelayError()组合多个 Observable 时,
一个 Observable发出 Error事件,
onError() 事件推迟到其他 Observable 发送结束后才触发
Observable.concatArrayDelayError( observable1, observable2, …).subscribe(…)
zip()按个数合并,即 1对1 合并
合并后新 Observable 的事件数量 = 多个 Observable 数量最少 的数量
observable1 [1,2,3]
observable2 [A,B,C,D]
合并后新Observable [1A, 2B, 3C] 按数量一对一合并
1、observable2 事件D 没有合并,但是会发送,订阅在新Observable上的观察者不会接收到事件D
2、若observable1 & observable2 最后都发送 onComplete()事件,则 事件D 不会发送
combineLatest()
两个 Observable 中的任何一个发送了数据后,
先发送了数据的 Observable 的最新一个数据 与 另一个 Observable 发送的每个数据结合

最终基于该函数的结果发送数据
合并规则,见下图
combineLatestDelayError()一个 Observable 的 onError() 事件,延迟到另一个 Observable 的事件发送完之后再发送
reduce()把 Observable 发送的事件聚合成1个事件 & 发送
第1次取前2个数据聚合,然后聚合结果与下1个数据继续进行聚合
Observable.just(1,2,3,4)
.reduce
(new BiFunction<Integer, Integer, Integer>())
假设 reduce() 函数 return event1 * event2;
结果:24
collect()将 Observable 发送的事件收集到一个数据结构里Observable.just(1, 2, 3 ,4, 5, 6)
.collect(new Callable<ArrayList>()
, new BiConsumer<ArrayList, Integer>())
.subscribe(…)
结果:发送一个List,List 数据:[1,2,3,4,5,6]
startWith()
startWithArray()
在一个 Observable 发送事件前,追加 发送一些数据 / 一个新的被观察者
Observable.just(4, 5, 6)
.startWith(0)
.startWithArray(1, 2, 3)

追加数据顺序 = 后调用先追加
结果:[1, 2, 3, 0, 4, 5, 6]
count()统计 Observable 发送事件的数量Observable.just(1, 2, 3, 4)
.count()

combineLatest 组合规则:
在这里插入图片描述

RxJava功能性操作符
操作符说明
subscribe()通过订阅(subscribe)连接观察者和被观察者
observable.subscribe(observer);
subscribeOn()设置 Observable 执行的线程
observeOn()设置 Observer 执行的线程
delay()延时操作
Observable.just(1, 2, 3)
.delay(3, TimeUnit.SECONDS) 延迟3s再发送
doXXX()在事件的生命周期中操作
.doOnEach():Observable 每发送1次事件,就调用1次
doOnNext():执行Next事件前调用
doAfterNext()执行Next事件后调用
doOnComplete():Observable正常发送事件完毕后调用
doOnError():Observable发送错误事件时调用
doOnSubscribe():观察者订阅时调用
doAfterTerminate():Observable 发送事件完毕后调用,无论正常发送完毕 / 异常终止
doFinally():最后执行
onErrorReturn()发送事件时,错误处理机制,可捕获在它之前发生的异常
onErrorResumeNext()拦截 Throwable 错误
遇到错误时,发送1个新的Observable
onExceptionResumeNext()拦截 Exception 错误
遇到错误时,发送1个新的Observable
retry()出现错误时,让 Observable 重新发送数据
若一直错误,则一直重新发送
retry(long times)出现错误时,让 Observable 重新发送数据,参数 = 重试次数
retry(Predicate predicate)出现错误后,判断是否需要重新发送数据(若需要重新发送& 持续遇到错误,则持续重试)
参数 = 判断逻辑
返回 true = 重新发送请求
返回 false = 不重新发送数据 & 调用观察者的 onError 结束
retry(new BiPredicate<Integer, Throwable>)出现错误后,判断是否需要重新发送数据(若需要重新发送& 持续遇到错误,则持续重试)
参数 = 判断逻辑
返回 true = 重新发送请求
返回 false = 不重新发送数据 & 调用观察者的 onError 结束

retry函数中,可获取重试的次数
retry(long time,Predicate predicate)出现错误后,判断是否需要重新发送数据(具备重试次数限制)
参数 = 设置重试次数 & 判断逻辑
retryUntil()遇到错误时,若需要重新发送 & 持续遇到错误,则持续重试
作用类似 retry(Predicate predicate)
唯一区别:返回 true 则 不重新发送数据事件
retryWhen()遇到错误时,将发生的错误传给一个新的 Observable
并决定是否需要重新订阅原始 Observable & 发送事件
1.若新的 Observable发送的事件 = Error事件,原始 Observable 不重新发送事件
发送 Error 事件后结束
2.新的 Observable 发送的事件 = Next事件 ,原始 Observable 重新发送事件
repeat()接收到.onCompleted()事件后,触发重新订阅 & 发送
默认运行在一个新的线程上
不传入参数 = 无限重复发送
repeatWhen()将原始 Observable 停止发送事件的标识(Complete() / Error())转换成1个 Object 类型数据
传递给1个新 Observable,以此决定是否重新订阅 & 发送原来的 Observable
新 Observable 返回1个 Complete / Error 事件,则不重新订阅
新 Observable 返回其余事件时,则重新订阅 & 发送原来的 Observable

线程调度

类型含义场景
Schedulers.immediate()当前线程 = 不指定线程默认
AndroidSchedulers.mainThread()Android主线程操作UI
Schedulers.newThread()常规新线程耗时等操作
Schedulers.io()io操作线程网络请求、读写文件等io密集型操作
Schedulers.computation()CPU计算操作线程大量计算操作

RxJava内部使用【线程池】来维护这些线程,所以线程的调度效率非常高

RxJava过滤操作符
操作符说明
filter()过滤 特定条件的事件
返回 true,则继续发送
返回 false,则不发送(即过滤)
ofType()筛选出 特定数据类型的数据
.ofType(Integer.class) // 筛选出 整型数据,其他类型的数据会被过滤掉
skip()/skipLast()跳过某个事件
Observable.just(1, 2, 3, 4, 5)
.skip(1) // 跳过正序的前1项,过滤掉了1
.skipLast(2) // 跳过正序的后2项,过滤掉了4,5
场景:跳过 一开始 EditText 无任何输入时的空值
RxTextView.textChanges(name).skip(1);
distinct()过滤 重复的事件
Observable.just(1, 2, 3, 1 , 2 )
.distinct() //过滤掉重复的 1,2
结果:1,2,3
distinctUntilChanged()过滤事件序列 连续重复的事件
Observable.just(1,2,3,1,2,3,3,4,4 )
.distinctUntilChanged() //过滤连续重复的3,4;非连续的不会过滤
结果:1,2,3,1,2,3,4
take()指定观察者最多能接收到的事件数量
observable.take(2) 指定观察者只能接收2个事件
takeLast()指定观察者只能接收到被观察者发送的最后几个事件
observable.takeLast(3) // 指定观察者只能接受 Observable 发送的最后3个事件
throttleFirst() / throttleLast()在某段时间内,只发送该段时间内第1次事件 / 最后1次事件
observable.throttleFirst(1, TimeUnit.SECONDS) //仅发送每1秒中,的第一个事件
observable.throttleLast(1, TimeUnit.SECONDS) // 仅发送每1秒中,的最后一个事件

运用:防止重复点击
sample()与 throttleLast() 操作符类似
在某段时间内,只发送该段时间内最新(最后)1次事件
throttleWithTimeout() / debounce()发送数据事件时,若2次发送事件的间隔<指定时间,就会丢弃前一次的数据

observable.throttleWithTimeout(1, TimeUnit.SECONDS)
// 丢弃间隔小于指定时间1s 的前一次数据
运用:输入框输入操作控制每指定时间触发一次回调
firstElement() / lastElement()仅选取第1个元素 / 最后一个元素
elementAt( index )指定接收某个元素(通过 索引值 确定),位置索引从0开始
.elementAt(6 ,10) // 默认值是10,位置6越界,则发送默认值10
elementAtOrError( index )指定接收某个元素(通过 索引值 确定),位置索引从0开始
越界时发送 NoSuchElementException 错误
RxJava背压

一种 控制事件流速 的策略,对超出缓存区大小的事件进行丢弃、保留、报错的措施。
在【异步订阅关系】中,控制事件发送 & 接收的速度

场景:比如,网络请求。

操作符说明特点
同步订阅Observer & Observable
工作【在同一线程】
Observable 每发送1个事件,必须等 Observer 接收& 处理后
才能继续发送下一事件
异步订阅Observer & Observable
工作【在不同线程】
Observable 不断发送,直到发送事件完毕
不需要 等待 Observer 接收& 处理
事件先发送到缓存区,Observer 从缓存区取出事件处理
问题Observable 发送事件速度
与 Observer 接收事件速度 不匹配
Observable 发送事件速度太快,Observer 来不及接收所有事件,
导致观察者无法及时响应 / 处理事件,
最终导致 缓存区溢出、事件丢失 & OOM
解决采用背压策略Flowable:RxJava 2.0 Observable 的一种新实现,
是背压策略实现的承载者
Flowable1、对应的 观察者 为 Subscriber
2、所有的操作符 强制支持背压
3、缓存区存放策略:类似队列,FIFO,先进先出
4、默认的缓存区(队列)大小 = 128
Flowable.create(
// 需要传入背压策略
new FlowableOnSubscribe() , BackpressureStrategy.ERROR
)
.subscribe(new Subscriber(…));
背压策略模式
BackpressureStrategy
当缓存区大小存满
Observable 继续发送事件时
处理策略
1)BackpressureStrategy.ERROR 抛出 MissingResourceException
2)BackpressureStrategy.MISSING 友好提示:缓冲区满了
3)BackpressureStrategy.BUFFER 将缓存区大小设置成无限大
4)BackpressureStrategy.DROP 超过缓存区大小(128) 的事件丢弃
5)BackpressureStrategy.LATEST 只保存最新(最后事件),超过缓存区大小的事件丢弃
背压策略选择1、手动创建FLowable 时,可传入参数选择背压策略
2、自动创建 FLowable 时,背压策略选择:
1) 默认 BackpressureStrategy.ERROR 模式
2) onBackpressureBuffer():缓存区设置成无限大
3) onBackpressureDrop():超过缓存区大小(128) 的事件丢弃
4) onBackpressureLatest():只保存最新(最后事件),超过缓存区大小的事件丢弃
背压策略—控制 Subscriber 接收事件 的速度
操作符说明实现
异步订阅响应式拉取:
Subscriber 按需接收事件
1、在观察者 Subscriber # onSubscribe(Subscription s) 方法中
调用 Subscription # request ( count )
指定 Subscriber 接收的事件数量

2、未设置 Subscription.request(long n),即说明观察者不接收事件
Flowable 能继续发送事件(存放在缓存区)
缓存区溢出时,报错 MissingResourceException

3、onSubscribe(Subscription s) 参数 Subscription
Subscription.cancel():作用等同于 Disposable.dispose()切断连接
Subscription.request(long n):指定 Subscriber 接收的事件数量
同步订阅不会出现 Flowable 发送事件速度 > Subscriber 接收事件速度
会出现Flowable 发送事件数量 > Subscriber 接收事件数量
1、同步订阅没有缓存区
Flowable 在发送1个事件后,必须等待 Subscriber 接收后,才能继续发下1个事件
2、如果 Subscriber 没有设置 Subscription.request(long n)
Flowable 发送第一个事件,就抛出 MissingResourceException
背压策略—控制 Flowable 发送事件 的速度
操作符说明
反馈控制Flowable 根据 Subscriber 的接收能力,控制发送事件速度
通过 Flowable 事件发射器 FlowableEmitter # requested() 方法控制流速
同步订阅FlowableEmitter.requested() 返回值 == Subscriber # Subscription.request(a) 的参数值
Flowable 通过 FlowableEmitter.requested() 返回值,知道了 Subscriber 接收事件的能力
根据该信息控制事件发送速度,达到观察者反向控制被观察者的效果
异步订阅1、Flowable FlowableEmitter.requested() == Flowable 线程中 RxJava 内部调用的 request(n)的n值
(n=128、96、0)

从而每次发送128、96、或0个事件给观察者
2、由于 Flowable 与 Subscriber 处于不同线程,
Flowable 无法通过 FlowableEmitter.requested() 知道观察者接收事件的能力,
只能通过 RxJava 内部固定设置,反向控制 Flowable 的发送事件速度
FlowableEmitter.requested()
事件发射器,可发送事件数
1、可叠加性
Subscriber 可连续要求接收事件,Flowable 会进行叠加、并一起发送
2、实时更新性
每次发送 Next 事件后, FlowableEmitter.requested() 返回值会实时更新
complete & error事件不算

3、异常
FlowableEmitter.requested() 返回值 = 0 时,代表观察者已经不可接收事件
此时,Flowable 继续发送事件,会抛出 MissingResourceException
RxJava运用场景
场景说明
网络请求轮询Observable
.interval(2 ,1 ,TimeUnit.SECONDS)
.doOnNext(//网络请求)
网络请求嵌套回调observable1.subscribeOn(Schedulers.io())// (初始被观察者)切换到IO线程进行网络请求1
.observeOn(AndroidSchedulers.mainThread()) // (新观察者)切换到主线程 处理网络请求1的结果
.doOnNext(// 第1次网络请求成功")
.observeOn(Schedulers.io()) //切换到IO线程去发起请求2
.flatMap(return observable2;)// 将网络请求1转换成网络请求2,即发送网络请求2
.observeOn(AndroidSchedulers.mainThread()) //(初始观察者)切换到主线程 处理网络请求2的结果
.subscribe(…)
从磁盘/内存缓存中 获取缓存数据Observable.concat(memory, disk, network)
.firstElement()
.subscribe(…)
按顺序串行发射
合并数据源 & 同时展示Observable
.merge
(network, file)
.subscribe()

Observable.zip(observable1, observable2, …)
联合判断多个事件Observable.combineLatest()

背压策略—控制 Subscriber 接收速度 代码实现:

Flowable.create(new FlowableOnSubscribe<Integer>() {
		@Override
		public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
			// 一共发送4个事件
			Log.d(TAG, "发送事件 1");
			emitter.onNext(1);
			Log.d(TAG, "发送事件 2");
			emitter.onNext(2);
			Log.d(TAG, "发送事件 3");
			emitter.onNext(3);
			Log.d(TAG, "发送事件 4");
			emitter.onNext(4);
			Log.d(TAG, "发送完成");
			emitter.onComplete();
		}
	}, BackpressureStrategy.ERROR)
		.subscribeOn(Schedulers.io()) // 设置被观察者在io线程中进行
		.observeOn(AndroidSchedulers.mainThread()) // 设置观察者在主线程中进行
		.subscribe(new Subscriber<Integer>() {
			@Override
			public void onSubscribe(Subscription s) {
				/* 对比Observer传入的Disposable参数,Subscriber此处传入的参数 = Subscription
				 * 相同点:Subscription参数具备Disposable参数的作用,即Disposable.dispose()切断连接, 同样的调用Subscription.cancel()切断连接
				 * 不同点:Subscription增加了void request(long n)
				 */

				/* 作用:决定观察者能够接收多少个事件
				 * 如设置了s.request(3),这就说明观察者能够接收3个事件(多出的事件存放在缓存区)
				 * 官方默认推荐使用Long.MAX_VALUE,即s.request(Long.MAX_VALUE);
				 */
				s.request(3);
			}
			...
		});

背压—控制 Flowable 发送事件 的速度 代码实现

  • 同步订阅 控制 Flowable

    Flowable.create(new FlowableOnSubscribe<Integer>() {
      		@Override
      		public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
      			// 获取 Subscriber 需要接收的事件数量 n
      			long n = emitter.requested();
      			// 根据 Subscriber 可接收数量,确定发射事件数 n
      			for (int i = 0; i < n; i++) {
      				emitter.onNext(i);//发射事件
      			}
      		}
      	}, BackpressureStrategy.ERROR)
      	.subscribe(new Subscriber<Integer>() {
      		@Override
      		public void onSubscribe(Subscription s) {
      			// 设置 Subscriber 每次接受 10个事件
      			s.request(10);
      		}
      		...
      	});
    
  • 异步订阅 控制 Flowable

    Flowable.create(new FlowableOnSubscribe<Integer>() {
      	@Override
      	public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
      	
      			/* 异步订阅时,这个值是 RxJava 内部调用 request(n)的参数值
      			* 该内部调用 会在一开始就调用 request(128)
      			* 与 Subscriber 中 request()传入值 无关
      			*/
      			long n = emitter.requested();
      			for (int i = 0; i < n; i++) {
      				emitter.onNext(i);//发射事件
      			}
      	}
      }, BackpressureStrategy.ERROR)
      		.subscribeOn(Schedulers.io()) //设置 Flowable 在io线程中进行
      		.observeOn(AndroidSchedulers.mainThread()) //设置 Subscriber 在主线程中进行
      		.subscribe(new Subscriber<Integer>() {
      			@Override
      			public void onSubscribe(Subscription s) {
      				/*
      				 * 该设置仅影响 Subscriber 线程中的 requested
      				 * 不会影响的 Flowable 的 FlowableEmitter.requested()的返回值
      				 * 因为 FlowableEmitter.requested()的返回值 取决于RxJava内部调用 request(n)
      				 * 而该内部调用会在一开始就调用 request(128)
      				 */
      				s.request(150);
      			}
      			...
      		});
    
RxJava运用场景
1、网络请求轮询

1)无条件网络请求

/*
 * 步骤1:采用interval()延迟发送
 * 注:此处主要展示无限次轮询,若要实现有限次轮询,仅需将interval()改成 intervalRange()即可
 **/
Observable.interval(2 ,1 ,TimeUnit.SECONDS)
	// 参数说明:
	// 参数1 = 第1次延迟时间;
	// 参数2 = 间隔时间数字;
	// 参数3 = 时间单位;
	// 该例子发送的事件特点:延迟2s后发送事件,每隔1秒产生1个数字(从0开始递增1,无限个)

	 /*
	  * 步骤2:每次发送数字前发送1次网络请求(doOnNext()在执行Next事件前调用)
	  * 即每隔1秒产生1个数字前,就发送1次网络请求,从而实现轮询需求
	  */
	 .doOnNext(new Consumer<Long>() {
		@Override
		public void accept(Long integer) throws Exception {
			Log.d(TAG, "第 " + integer + " 次轮询" );
			//这里实现网络请求(需要自己设置线程)
			...
		}
	}).subscribe(new Observer<Long>() {
		...
	});

2)有条件网络请求

GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
// 采用Observable<...>形式 对 网络请求 进行封装
Observable<Translation> observable = request.getCall();
// 发送网络请求 & 通过repeatWhen()进行轮询
observable.repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() {
	@Override
	// 在Function函数中,必须对输入的 Observable<Object>进行处理,此处使用flatMap操作符接收上游的数据
	public ObservableSource<?> apply(@NonNull Observable<Object> objectObservable) throws Exception {
		// 将原始 Observable 停止发送事件的标识(Complete() /  Error())转换成1个 Object 类型数据传递给1个新被观察者(Observable)
		// 以此决定是否重新订阅 & 发送原来的 Observable,即轮询
		// 此处有2种情况:
		// 1. 若返回1个Complete() /  Error()事件,则不重新订阅 & 发送原来的 Observable,即轮询结束
		// 2. 若返回其余事件,则重新订阅 & 发送原来的 Observable,即继续轮询
		return objectObservable.flatMap(new Function<Object, ObservableSource<?>>() {
			@Override
			public ObservableSource<?> apply(@NonNull Object throwable) throws Exception {

				// 加入判断条件:当轮询次数 = 5次后,就停止轮询
				if (i > 3) {
					// 此处选择发送onError事件以结束轮询,因为可触发下游观察者的onError()方法回调
					return Observable.error(new Throwable("轮询结束"));
				}
				// 若轮询次数<4次,则发送1Next事件以继续轮询
				// 注:此处加入了delay操作符,作用 = 延迟一段时间发送(此处设置 = 2s),以实现轮询间间隔设置
				return Observable.just(1).delay(2000, TimeUnit.MILLISECONDS);
			}
		});

	}
}).subscribeOn(Schedulers.io())               // 切换到IO线程进行网络请求
	.observeOn(AndroidSchedulers.mainThread())  // 切换回到主线程 处理请求结果
	.subscribe(new Observer<Translation>() {
		...
	});
2、网络请求嵌套回调
// 创建 网络请求接口 的实例
GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
// 采用Observable<...>形式 对 2个网络请求 进行封装
observable1 = request.getCall();
observable2 = request.getCall_2();

observable1.subscribeOn(Schedulers.io())               // (初始被观察者)切换到IO线程进行网络请求1
		   .observeOn(AndroidSchedulers.mainThread())  // (新观察者)切换到主线程 处理网络请求1的结果
		   .doOnNext(new Consumer<Translation1>() {
			@Override
			public void accept(Translation1 result) throws Exception {
				Log.d(TAG, "第1次网络请求成功");
				// 对第1次网络请求返回的结果进行操作 = 显示翻译结果
				result.show();						
			}
		})
		// (新被观察者,同时也是新观察者)切换到IO线程去发起登录请求
		.observeOn(Schedulers.io()) 
		// 特别注意:因为flatMap 是对初始被观察者作变换,所以对于旧被观察者,它是新观察者,所以通过observeOn切换线程
		// 但对于初始观察者,它则是新的被观察者
		.flatMap(new Function<Translation1, ObservableSource<Translation2>>() { // 作变换,即作嵌套网络请求
			@Override
			public ObservableSource<Translation2> apply(Translation1 result) throws Exception {
				// 将网络请求1转换成网络请求2,即发送网络请求2
				return observable2;
			}
		})
		.observeOn(AndroidSchedulers.mainThread())  //(初始观察者)切换到主线程 处理网络请求2的结果
		.subscribe(new Consumer<Translation2>() {
			@Override
			public void accept(Translation2 result) throws Exception {
				Log.d(TAG, "第2次网络请求成功");
				result.show();
				// 对第2次网络请求返回的结果进行操作 = 显示翻译结果
			}
		}, new Consumer<Throwable>() {
			@Override
			public void accept(Throwable throwable) throws Exception {
				System.out.println("登录失败");
			}
		});
3、从磁盘/内存缓存中 获取缓存数据
// 该2变量用于模拟内存缓存 & 磁盘缓存中的数据
   String memoryCache = null;
   String diskCache = "从磁盘缓存中获取数据";
   
   /*
    * 设置第1个Observable:检查内存缓存是否有该数据的缓存
    **/
   Observable<String> memory = Observable.create(new ObservableOnSubscribe<String>() {
       @Override
       public void subscribe(ObservableEmitter<String> emitter) throws Exception {
           // 先判断内存缓存有无数据
           if (memoryCache != null) {
               // 若有该数据,则发送
               emitter.onNext(memoryCache);
           } else {
               // 若无该数据,则直接发送结束事件
               emitter.onComplete();
           }
       }
   });

   /*
    * 设置第2个 Observable:检查磁盘缓存是否有该数据的缓存
    **/
   Observable<String> disk = Observable.create(new ObservableOnSubscribe<String>() {
       @Override
       public void subscribe(ObservableEmitter<String> emitter) throws Exception {
           // 先判断磁盘缓存有无数据
           if (diskCache != null) {
               // 若有该数据,则发送
               emitter.onNext(diskCache);
           } else {
               // 若无该数据,则直接发送结束事件
               emitter.onComplete();
           }
       }
   });

   /*
    * 设置第3个 Observable:通过网络获取数据
    **/
   Observable<String> network = Observable.just("从网络中获取数据");
   // 此处仅作网络请求的模拟
   /*
    * 通过 concat() 和 firstElement()操作符实现缓存功能
    **/

   // 1. 通过concat()合并memory、disk、network 3个被观察者的事件(即检查内存缓存、磁盘缓存 & 发送网络请求)
   //    并将它们按顺序串联成队列
   Observable.concat(memory, disk, network)
           // 2. 通过firstElement(),从串联队列中取出并发送第1个有效事件(Next事件),
		//    即依次判断检查memory、disk、network
           .firstElement()
           // 即本例的逻辑为:
           // a. firstElement()取出第1个事件 = memory,即先判断内存缓存中有无数据缓存;
		//    由于memoryCache = null,即内存缓存中无数据,所以发送结束事件(视为无效事件)
		
           // b. firstElement()继续取出第2个事件 = disk,即判断磁盘缓存中有无数据缓存:
		//    由于diskCache ≠ null,即磁盘缓存中有数据,所以发送Next事件(有效事件)
		
           // c. 即firstElement()已发出第1个有效事件(disk事件),所以停止判断。
           
           // 3. 观察者订阅
           .subscribe(new Consumer<String>() {
               @Override
               public void accept( String s) throws Exception {
                   Log.d(TAG,"最终获取的数据来源 =  "+ s);
               }
           });
4、合并数据源 & 同时展示

1)merge()

// 用于存放最终展示的数据
String result = "数据源来自 = " ;		   
/*
 * 设置第1个Observable:通过网络获取数据
 * 此处仅作网络请求的模拟
 **/
Observable<String> network = Observable.just("网络");
/*
 * 设置第2个Observable:通过本地文件获取数据
 * 此处仅作本地文件请求的模拟
 **/
Observable<String> file = Observable.just("本地文件");
/*
 * 通过merge()合并事件 & 同时发送事件
 **/
Observable.merge(network, file)
	.subscribe(new Observer<String>() {
		@Override
		public void onSubscribe(Disposable d) {
		}

		@Override
		public void onNext(String value) {
			Log.d(TAG, "数据源有: "+ value  );
			result += value + "+";
		}

		@Override
		public void onError(Throwable e) {
			Log.d(TAG, "对Error事件作出响应");
		}

		// 接收合并事件后,统一展示
		@Override
		public void onComplete() {
			Log.d(TAG, "获取数据完成");
			Log.d(TAG,  result  );
		}
	});

2)zip()

// 步骤2:创建 网络请求接口 的实例
GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
 // 步骤3:采用Observable<...>形式 对 2个网络请求 进行封装
observable1 = request.getCall().subscribeOn(Schedulers.io()); // 新开线程进行网络请求1
observable2 = request.getCall_2().subscribeOn(Schedulers.io());// 新开线程进行网络请求2
// 即2个网络请求异步 & 同时发送

// 步骤4:通过使用Zip()对两个网络请求进行合并再发送
Observable.zip(observable1, observable2,
	new BiFunction<Translation1, Translation2, String>() {
		// 注:创建 BiFunction 对象传入的第3个参数 = 合并后数据的数据类型
		@Override
		public String apply(Translation1 translation1, ranslation2 translation2) throws Exception {
			return translation1.show() + " & " +translation2.show();
		}
	}).observeOn(AndroidSchedulers.mainThread()) // 在主线程接收 & 处理数据
	.subscribe(new Consumer<String>() {
		// 成功返回数据时调用
		@Override
		public void accept(String combine_infro) throws Exception {
			// 结合显示2个网络请求的数据结果
			Log.d(TAG, "最终接收到的数据是:" + combine_infro);
		}
	}, new Consumer<Throwable>() {
		// 网络请求错误时调用
		@Override
		public void accept(Throwable throwable) throws Exception {
			System.out.println("登录失败");
		}
	});
5、联合判断多个事件
/*
 * 步骤2:为每个EditText设置被观察者,用于发送监听事件
 * 说明:
 * 1. 此处采用了RxBinding:RxTextView.textChanges(name) = 对控件数据变更进行监听(功能类似TextWatcher),
	  需要引入依赖:compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
 * 2. 传入EditText控件,点击任1个EditText输入时,都会发送数据事件 = Function3()的返回值(下面会详细说明)
 * 3. 采用skip(1)原因:跳过 一开始 EditText无任何输入时的空值
 */
Observable<CharSequence> nameObservable = RxTextView.textChanges(name).skip(1);
   Observable<CharSequence> ageObservable = RxTextView.textChanges(age).skip(1);
   Observable<CharSequence> jobObservable = RxTextView.textChanges(job).skip(1);
   /*
    * 步骤3:通过combineLatest()合并事件 & 联合判断
    */
   Observable.combineLatest(nameObservable,ageObservable,jobObservable,new Function3<CharSequence, CharSequence, CharSequence,Boolean>() {
       @Override
       public Boolean apply(@NonNull CharSequence charSequence, @NonNull CharSequence charSequence2, @NonNull CharSequence charSequence3) throws Exception {
           /*
            * 步骤4:规定表单信息输入不能为空
            **/
           // 1. 姓名信息
           boolean isUserNameValid = !TextUtils.isEmpty(name.getText()) ;
           // 除了设置为空,也可设置长度限制
           // boolean isUserNameValid = !TextUtils.isEmpty(name.getText()) && (name.getText().toString().length() > 2 && name.getText().toString().length() < 9);
           // 2. 年龄信息
           boolean isUserAgeValid = !TextUtils.isEmpty(age.getText());
           // 3. 职业信息
           boolean isUserJobValid = !TextUtils.isEmpty(job.getText()) ;
           /*
            * 步骤5:返回信息 = 联合判断,即3个信息同时已填写,"提交按钮"才可点击
            **/
           return isUserNameValid && isUserAgeValid && isUserJobValid;
       }})
	.subscribe(new Consumer<Boolean>() {
		@Override
		public void accept(Boolean s) throws Exception {
			/*
			 * 步骤6:返回结果 & 设置按钮可点击样式
			 **/
			Log.e(TAG, "提交按钮是否可点击: "+s);
			list.setEnabled(s);
		}
	});

===================== 后面内容可看额不看 ====================

详细说明

4、使用步骤

1)创建被观察者(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();
	}
});

方法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();
 */ 

2)创建观察者(Observer) 并 定义响应事件行为
事件类型包括:Next 事件、 Complete 事件 & Error 事件。

  • i.Next 普通事件
    向观察者发送需要响应事件的信号
    被观察者可发送无限个Next 事件;观察者可接收无限个Next 事件
    onNext()

  • ii.Complete 事件队列完结 事件;(RxJava 把所有事件当作队列处理)
    标志 被观察者 不再发送普通事件(Next)
    当 被观察者 发送要给Complete 事件后:
    被观察者在Complete 事件后的事件,将会继续发送,
    但观察者收到 Complete 事件后,将不再继续接收任何事件。

    被观察者 可以不发送Complete 事件
    onComplete()

  • iii.Error 事件队列异常 事件
    标志 事件处理过程中出现异常(此时队列自动终止,不允许再有事件发送)

    当 被观察者 发送一个 Error 事件后:
    被观察者在 Error事件后的事件将会继续发送,
    但观察者收到Error事件后,将不再继续接收任何事件。

    被观察者 可以不发送Error 事件
    onError()

  • iv.在要给正确运行的事件序列中:
    onComplete() & onError() 二者互斥
    onComplete() & onError() 是唯一的

方式一:创建观察者 (Observer )对象,实现 onSubscribe() 方法
观察者接收事件前,默认最先调用复写 onSubscribe()

Observer<Integer> observer = new Observer<Integer>() {		
	@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 接口进行了扩展
观察者接收事件前,默认最先调用复写 onSubscribe()

Subscriber<Integer> subscriber = new Subscriber<Integer>() {

	@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事件作出响应");
	}
};

Subscriber 抽象类与 Observer 接口的区别

  • 相同点:二者基本使用方式完全一致
    在RxJava的 subscribe 过程中,Observer总是会先被转换成 Subscriber 再使用

  • 不同点:Subscriber抽象类对 Observer 接口进行了扩展,新增了两个方法

    1. onStart():响应事件前调用 ,用于做一些 初始化工作

    2. unsubscribe():用于取消订阅。该方法被调用后,观察者将不再接收 & 响应事件
      调用该方法前,先使用 isUnsubscribed() 判断状态
      确定被观察者 Observable 是否还持有观察者 Subscriber 的引用,
      如果引用不能及时释放,就会出现内存泄露

  • 3)通过订阅(Subscribe) 连接观察者和被观察者

    具体实现:
    observable.subscribe(observer);
    或者
    observable.subscribe(subscriber);

    Observable.subscribe(Subscriber) 的内部实现:

    public Subscription subscribe(Subscriber subscriber) {
      	// 步骤1中 观察者  subscriber抽象类复写的方法,用于初始化工作
      	subscriber.onStart();
      	
      	/* 通过该调用,从而回调观察者中的对应方法,从而响应被观察者生产的事件
      	 * 从而实现被观察者调用了观察者的回调方法 & 由被观察者向观察者的事件传递,即观察者模式
      	 *
      	 * 同时也看出:Observable只是生产事件,真正的发送事件是在它被订阅的时候
      	 * 即当 subscribe() 方法执行时
      	 */
      	onSubscribe.call(subscriber);					
    }
    
5、基于事件流的链式调用
// RxJava的链式操作
   Observable.create(new ObservableOnSubscribe<Integer>() {
   // 1. 创建被观察者 & 生产事件
       @Override
       public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
		//emitter 是事件发射器
           emitter.onNext(1);
           emitter.onNext(2);
           emitter.onNext(3);
           emitter.onComplete();
       }
	// 2. 通过通过订阅(subscribe)连接观察者和被观察者
   }).subscribe(new Observer<Integer>() {// 3. 创建观察者 & 定义响应事件的行为
       
	// 默认最先调用复写的 onSubscribe()
       @Override
       public void onSubscribe(Disposable d) {
           Log.d(TAG, "开始采用subscribe连接");
       }            

       @Override
       public void onNext(Integer value) {
           Log.d(TAG, "对Next事件"+ value +"作出响应"  );
       }

       @Override
       public void onError(Throwable e) {
           Log.d(TAG, "对Error事件作出响应");
       }

       @Override
       public void onComplete() {
           Log.d(TAG, "对Complete事件作出响应");
       }
   });

【整体方法调用顺序】:
观察者.onSubscribe() > 被观察者.subscribe() > 观察者.onNext() > 观察者.onComplete()

6、多个函数式接口,实现更便捷的观察者模式

Action、BiConsumer、BiFunction、Cancellable、Consumer、Function、Function3…

Observable.just("hello").subscribe(new Consumer<String>() {
	
    // 每次接收到 Observable 的事件都会调用 Consumer.accept()
    @Override
    public void accept(String s) throws Exception、
        System.out.println(s);
    }
});
7、被观察者 Observable 的 subscribe() 具备多个重载的方法
  • 1)多个重载方法的说明

    subscribe() 无参数,表示被观察者可以发送事件,观察者对事件【不作出任何响应】

    public final Disposable subscribe() {}
    

    表示 观察者只对【Next事件】作出响应

    public final Disposable subscribe(Consumer<? super T> onNext) {}
    

    表示 观察者只对【Next事件 & Error事件】作出响应

    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) {} 
    

    表示 观察者只对【Next事件、Error事件 & Complete事件】作出响应

    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete) {}
    

    表示 观察者只对【Next事件、Error事件 、Complete事件 & onSubscribe事件】作出响应

    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) {}
    
  • 2)采用 Disposable.dispose() 切断观察者 与 被观察者 之间的连接

    观察者 无法继续 接收 被观察者的事件,但被观察者可以继续发送事件

    // 主要在观察者 Observer中 实现
    Observer<Integer> observer = new Observer<Integer>() {
    	// 1. 定义Disposable类变量
    	private Disposable mDisposable;
    
    	@Override
    	public void onSubscribe(Disposable d) {
    		Log.d(TAG, "开始采用subscribe连接");
    		// 2. 对Disposable类变量赋值
    		mDisposable = d;
    	}
    
    	@Override
    	public void onNext(Integer value) {
    		Log.d(TAG, "对Next事件"+ value +"作出响应"  );
    		if (value == 2) {// 设置在接收到第二个事件后切断观察者和被观察者的连接
    			mDisposable.dispose();
    			Log.d(TAG, "已经切断了连接:" + mDisposable.isDisposed());
    		}
    	}
    
    	@Override
    	public void onError(Throwable e) {
    		Log.d(TAG, "对Error事件作出响应");
    	}
    
    	@Override
    	public void onComplete() {
    		Log.d(TAG, "对Complete事件作出响应");
    	}
    };
    

二、RxJava常用【创建操作符】 create、just、from、interval、range等

1、create() 创建一个被观察者对象(Observable)
   /** 通过create()创建被观察者 Observable 对象
	* 传入参数: OnSubscribe 对象
	*
	* 当 Observable 被订阅时,OnSubscribe 的 call() 方法会自动被调用,即事件序列就会依照设定依次被触发
	* 即观察者会依次调用对应事件的复写方法从而响应事件
	* 从而实现由被观察者向观察者的事件传递 & 被观察者调用了观察者的回调方法 ,即观察者模式
	*/
	Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
		
	   
		// 2. 在复写的subscribe() 里定义【需要发送的事件】
		@Override
		public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
			// 通过 ObservableEmitter类对象 产生 & 发送事件
			// ObservableEmitter类介绍
				// a. 定义:事件发射器
				// b. 作用:定义需要发送的事件 & 向观察者发送事件
				// 注:建议发送事件前检查观察者的isUnsubscribed状态,以便在没有观察者时,让Observable停止发射数据
				if (!observer.isUnsubscribed()) {
					   emitter.onNext(1);
					   emitter.onNext(2);
					   emitter.onNext(3);
			}
			emitter.onComplete();
		}
	});
2、just() 快速创建被观察者对象,直接发送传入的事件,最多只能发送10个参数
场景:快速创建 被观察者对象(Observable) & 发送10个以下事件

// 1.创建时传入整型1、2、3、4
   // 在创建后就会发送这些对象,相当于执行了onNext(1)、onNext(2)、onNext(3)、onNext(4)
   Observable.just(1, 2, 3,4)   
       // 至此,一个Observable对象创建完毕,以下步骤仅为展示一个完整demo,可以忽略
       // 2. 通过通过订阅(subscribe)连接观察者和被观察者
       // 3. 创建观察者 & 定义响应事件的行为
	.subscribe(new Observer<Integer>() {
       ...
   });
3、fromArray()
快速创建1个被观察者对象,直接发送传入的数组数据,会将数组中的数据转为 Observable 对象

场景:1)快速创建 被观察者对象(Observable) & 发送10个以上事件(数组形式)
	  2)数组元素遍历
	  
// 1. 设置需要传入的数组
Integer[] items = { 0, 1, 2, 3, 4 };
   // 2. 创建被观察者对象(Observable)时传入数组,在创建后就会将该数组转换成 Observable & 发送该对象中的所有数据
   Observable.fromArray(items) 
	.subscribe(...);

注:若直接传递一个list集合进去,否则会直接把list当做一个数据元素发送
4、fromIterable()
快速创建1个被观察者对象(Observable),直接发送 传入的集合List数据

场景:1)快速创建 被观察者对象(Observable) & 发送10个以上事件(集合形式)
	  2)集合元素遍历

Observable.fromIterable(list)
           .subscribe(...);
5、empty()
/*该方法创建的被观察者对象发送事件的特点:仅发送Complete事件,直接通知完成
 * 观察者接收后会直接调用onCompleted()
 */
Observable observable = Observable.empty(); 
6、error()
	/* 该方法创建的被观察者对象发送事件的特点:仅发送Error事件,直接通知异常
	 * 可自定义异常,观察者接收后会直接调用onError()
	 */ 
	Observable observable = Observable.error(new RuntimeException())
7、never()
	/* 该方法创建的被观察者对象发送事件的特点:不发送任何事件
	 * 观察者接收后什么都不调用
	 */
	Observable observable = Observable.never();
8、defer() 延迟创建 Observable
	直到有观察者(Observer)订阅时,才动态创建被观察者对象(Observable) & 发送事件
	
	场景:动态创建被观察者对象(Observable) & 获取最新的 Observable 对象数据
	
	// 1. 第1次对i赋值
    Integer i = 10;
    // 2. 通过defer 定义被观察者对象,此时被观察者对象还没创建
    Observable<Integer> observable = Observable.defer(new Callable<ObservableSource<? extends Integer>>() {
        @Override
        public ObservableSource<? extends Integer> call() throws Exception {
            return Observable.just(i);
        }
    });
	// 2. 第2次对i赋值,因为是在订阅时才创建,所以i值会取第2次的赋值
    i = 15;
    // 3. 观察者开始订阅,此时,才会调用defer()创建被观察者对象(Observable)
    observable.subscribe(...);
9、timer()
	快速创建1个被观察者对象(Observable),延迟指定时间后,调用一次 onNext(0)
	
	场景:延迟指定时间,发送一个0 (Long类型),一般用于检测
	
	timer()操作符默认运行在一个新线程上
	
	可自定义线程调度器(第3个参数):timer(long,TimeUnit,Scheduler) 
	
	// 该例子 = 延迟2s后,发送一个long类型数值
    Observable.timer(2, TimeUnit.SECONDS) 
              .subscribe(new Observer<Long>() {
        ...
    });
10、interval()
	快速创建1个被观察者对象(Observable),每隔指定时间 就发送 事件
	
	发送的事件序列 = 从0开始、无限递增1的的整数序列
	
	interval()默认在computation调度器上执行
	可自定义指定线程调度器(第3个参数):interval(long,TimeUnit,Scheduler)
	
   /* 参数说明:
    * 	参数1 = 第1次延迟时间;
    * 	参数2 = 间隔时间数字;
    * 	参数3 = 时间单位;
	*/
    Observable.interval(3 ,1 ,TimeUnit.SECONDS)
            // 该例子发送的事件序列特点:延迟3s后发送事件,每隔1秒产生1个数字(从0开始递增1,无限个)
            .subscribe(new Observer<Long>() {
                ...
            });
11、intervalRange()
	快速创建1个被观察者对象(Observable),每隔指定时间 就发送 事件,可指定发送的数据的数量

	a. 发送的事件序列 = 从0开始、无限递增1的的整数序列
	b. 作用类似于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,无限个)
			*/
            .subscribe(new Observer<Long>() {
                ...
            });
12、range()
	快速创建1个被观察者对象(Observable),连续发送 1 个事件序列,可指定范围
	
	a. 发送的事件序列 = 从0开始、无限递增1的的整数序列
	b. 作用类似于intervalRange(),但区别在于:无延迟发送事件
	
	
	/* 参数说明:
    * 	参数1 = 事件序列起始点;
    * 	参数2 = 事件数量;
    * 	注:若设置为负数,则会抛出异常
	*/
    Observable.range(3 ,10)
            // 该例子发送的事件序列特点:从3开始发送,每次发送事件递增1,一共发送10个事件
            .subscribe(new Observer<Integer>() {
                ...
            });
13、rangeLong()
	类似 range(),区别在于该操作符支持数据类型 = Long
	
	使用方式与 range()类似。

三、RxJava常用变换操作符 map()、flatMap()、concatMap()、buffer()

1、map()
	将被观察者发送的事件转换为任意的类型事件
	
	场景:数据类型转换
	
	 //创建被观察者
    Observable.create(new ObservableOnSubscribe<Integer>() {

        // 1. 被观察者发送事件 = 参数为整型 = 1、2、3
        @Override
        public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
            emitter.onNext(1);
            emitter.onNext(2);
            emitter.onNext(3);
        }
        // 2. 使用Map变换操作符中的Function函数对被观察者发送的事件进行统一变换:整型变换成字符串类型
    }).map(new Function<Integer, String>() {
        @Override
        public String apply(Integer integer) throws Exception {
            return "使用 Map变换操作符 将事件" + integer +"的参数从 整型"+integer + " 变换成 字符串类型" + integer ;
        }
    }).subscribe(new Consumer<String>() {
        // 3. 观察者接收事件时,是接收到变换后的事件 = 字符串类型
        @Override
        public void accept(String s) throws Exception {
            Log.d(TAG, s);
        }
    });
2、flatMap()
	将被观察者发送的事件进行 拆分 & 单独转换,再合并成一个新的事件序列,最后再进行发送。
	
	场景:无序的将被观察者的整个事件序列进行变换。
	
	【新合并生成的事件序列顺序是无序的,即 与旧序列发送事件的顺序无关】
	
	步骤:
		i.为事件序列中每个事件都创建一个 Observable 对象
		
		ii.将对每个 原始事件 转换后的 新事件,都放入到对应 Observable 对象
		
		iii.将新建的每个 Observable 都合并到一个新建的、总的 Observable 对象
		
		iv.新建的、总的 Observable 对象,将 新合并的事件序列,发送给观察者。
			
	
	// 创建被观察者
    Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
            emitter.onNext(1);
            emitter.onNext(2);
            emitter.onNext(3);
        }
        // 采用flatMap()变换操作符
    }).flatMap(new Function<Integer, ObservableSource<String>>() {
        @Override
        public ObservableSource<String> apply(Integer integer) throws Exception {
            final List<String> list = new ArrayList<>();
            for (int i = 0; i < 3; i++) {
				// 通过flatMap中,将被观察者生产的事件序列先进行拆分
				// 再将每个事件转换为一个新的发送三个String事件
                // 最终合并,再发送给被观察者
				
                list.add("我是事件 " + integer + "拆分后的子事件" + i);
            }
            return Observable.fromIterable(list);
        }
    }).subscribe(new Consumer<String>() {
        @Override
        public void accept(String s) throws Exception {
            Log.d(TAG, s);
        }
    });
3、concatMap()
	作用类似flatMap()操作符
	
	与flatMap()区别:拆分 & 重新合并生成的 事件序列 的顺序 = 被观察者旧序列生产的顺序。
	
	场景:有序的将被观察者发送的整个事件序列进行转换
	
	【新合并生成的事件序列顺序是有序的,即 严格按照旧序列发送事件的顺序】
	
	// 创建被观察者
    Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
            emitter.onNext(1);
            emitter.onNext(2);
            emitter.onNext(3);
        }
        // 采用concatMap()变换操作符
    }).concatMap(new Function<Integer, ObservableSource<String>>() {
        @Override
        public ObservableSource<String> apply(Integer integer) throws Exception {
			// 通过concatMap中将被观察者生产的事件序列先进行拆分,
			// 再将每个事件转换为一个新的发送三个String事件
			// 最终合并,再发送给被观察者
            final List<String> list = new ArrayList<>();
            for (int i = 0; i < 3; i++) {
                list.add("我是事件 " + integer + "拆分后的子事件" + i);
            }
            return Observable.fromIterable(list);
        }
    }).subscribe(new Consumer<String>() {
        @Override
        public void accept(String s) throws Exception {
            Log.d(TAG, s);
        }
    });
4、buffer()
	定期从 被观察者(Obervable)需要发送的事件中 获取一定数量的事件 & 放到缓存区中,最终发送
	
	场景:缓存 被观察者 发送的事件。
	
	// 被观察者 需要发送5个数字
    Observable.just(1, 2, 3, 4, 5)
		
		/* 设置缓存区大小 & 步长
		 * 缓存区大小 = 每次从被观察者中获取的事件数量
	     * 步长 = 每次获取新事件的数量
	     */
		.buffer(3, 1) 
		.subscribe(new Observer<List<Integer>>() {
			@Override
			public void onSubscribe(Disposable d) {

			}
			@Override
			public void onNext(List<Integer> stringList) {
				//
				Log.d(TAG, " 缓存区里的事件数量 = " +  stringList.size());
				for (Integer value : stringList) {
					Log.d(TAG, " 事件 = " + value);
				}
			}

			@Override
			public void onError(Throwable e) {
				Log.d(TAG, "对Error事件作出响应" );
			}

			@Override
			public void onComplete() {
				Log.d(TAG, "对Complete事件作出响应");
			}
		});
	这里表示,每次从Observable 中获取3条数据放到缓冲区中发送。
	每发送完一次,向右偏移1位,继续从Observable 中获取数据。
	
	结果:
		第一次,缓存区事件数量3,事件1、2、3
		第二次,缓存区事件数量3,事件2、3、4
		第三次,缓存区事件数量3,事件3、4、5
		第四次,缓存区事件数量2,事件4、5
		第五次,缓存区事件数量1,事件5
		对Complete事件作出响应

四、RxJava常用组合、合并操作符 combineLatest、join、merge、zip等

组合操作符:组合多个被观察者(Observable) & 合并需要发送的事件
1、组合多个被观察者

1)按发送顺序 concat()、concatArray()

组合多个被观察者一起发送数据,合并后 【按发送顺序 串行执行
concat()组合被观察者数量 <= 4个,而concatArray()则可 > 4个

// concat():组合多个被观察者(≤4个)一起发送数据,串行执行
Observable.concat(Observable.just(1, 2, 3),
			   Observable.just(4, 5, 6),
			   Observable.just(7, 8, 9),
			   Observable.just(10, 11, 12))
            .subscribe(new Observer<Integer>() {
              ...
          });

// concatArray():组合多个被观察者一起发送数据(可>4个),串行执行
Observable.concatArray(Observable.just(1, 2, 3),
                     Observable.just(4, 5, 6),
                     Observable.just(7, 8, 9),
                     Observable.just(10, 11, 12),
                     Observable.just(13, 14, 15))
            .subscribe(new Observer<Integer>() {
              ...
          });

2)按时间 merge()、mergeArray()

组合多个被观察者一起发送数据,合并后 【按时间线 并行执行
merge()组合被观察者数量≤4个,而mergeArray() 则可>4个

// merge():组合多个被观察者(<= 4个)一起发送数据
// 注:合并后按照时间线并行执行
Observable.merge(
		// 从0开始发送、共发送3个数据、第1次事件延迟发送时间 = 1s、间隔时间 = 1s
		Observable.intervalRange(0, 3, 1, 1, TimeUnit.SECONDS), 
		// 从2开始发送、共发送3个数据、第1次事件延迟发送时间 = 1s、间隔时间 = 1s
		Observable.intervalRange(2, 3, 1, 1, TimeUnit.SECONDS)) 
            .subscribe(new Observer<Long>() {
		  /* 输出结果:
		   * 	两个被观察者发送事件并行执行
		   *    输出结果 = 0,2 -> 1,3 -> 2,4
		   */
		  ...
          });

// mergeArray() = 组合4个以上的被观察者一起发送数据,此处不作过多演示,类似concatArray()

3)错误处理 concatDelayError()、mergeDelayError()

使用 concat()、merge()操作符时,若其中一个被观察者发出onError()事件,
则会马上终止其他被观察者继续发送事件。

若希望onError()事件推迟到其他被观察者发送事件结束后才触发,
需要使用对应的 concatDelayError()、mergeDelayError()操作符。

Observable.concatArrayDelayError(
          Observable.create(new ObservableOnSubscribe<Integer>() {
              @Override
              public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                  emitter.onNext(1);
                  emitter.onNext(2);
                  emitter.onNext(3);
                  
                  // 发送Error事件,因为使用了concatDelayError,所以第2个Observable将会发送事件,
                  // 等发送完毕后,再发送错误事件
                  emitter.onError(new NullPointerException()); 
                  emitter.onComplete();
              }
          }),
          Observable.just(4, 5, 6))
          .subscribe(new Observer<Integer>() {
		//结果:第1个被观察者的Error事件,将在第2个被观察者发送完事件后再继续发送
		// 1、2、3、4、5、6、Error
              ...
          });
2、合并多个事件

对多个被观察者中的【事件】进行合并处理

1)按数量 zip()
合并 多个 Observable 发送的事件,生成一个新的事件序列(即组合过后的事件序列)
并最终发送。

事件组合方式 = 严格按照原先事件序列 进行对位合并

合并后新 Observable 的事件数量 = 多个被观察者(Observable)中 数量最少 的数量

场景:不同数据源的数据,需要统一结合后再处理。

【1】创建第1个被观察者
Observable<Integer> observable1 = Observable.create(new ObservableOnSubscribe<Integer>() {
	@Override
	public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
		Log.d(TAG, "被观察者1发送了事件1");
		emitter.onNext(1);
		// 为了方便展示效果,所以在发送事件后加入1s的延迟
		Thread.sleep(1000);

		Log.d(TAG, "被观察者1发送了事件2");
		emitter.onNext(2);
		Thread.sleep(1000);

		Log.d(TAG, "被观察者1发送了事件3");
		emitter.onNext(3);
		Thread.sleep(1000);

		emitter.onComplete();
	}
}).subscribeOn(Schedulers.io()); // 设置被观察者1在工作线程1中工作

【2】创建第2个被观察者
Observable<String> observable2 = Observable.create(new ObservableOnSubscribe<String>() {
	@Override
	public void subscribe(ObservableEmitter<String> emitter) throws Exception {
		Log.d(TAG, "被观察者2发送了事件A");
		emitter.onNext("A");
		Thread.sleep(1000);

		Log.d(TAG, "被观察者2发送了事件B");
		emitter.onNext("B");
		Thread.sleep(1000);

		Log.d(TAG, "被观察者2发送了事件C");
		emitter.onNext("C");
		Thread.sleep(1000);

		Log.d(TAG, "被观察者2发送了事件D");
		emitter.onNext("D");
		Thread.sleep(1000);

		emitter.onComplete();
	}
}).subscribeOn(Schedulers.newThread());// 设置被观察者2在工作线程2中工作
// 假设不作线程控制,则该两个被观察者会在同一个线程中工作,
// 即发送事件存在先后顺序,而不是同时发送

【3】使用zip变换操作符进行事件合并
// 注:创建BiFunction对象传入的第3个参数 = 合并后数据的数据类型
Observable.zip(observable1, observable2, new BiFunction<Integer, String, String>() {
	@Override
	public String apply(Integer integer, String string) throws Exception {
		return  integer + string;
	}
}).subscribe(new Observer<String>() {
	//1、尽管被观察者2的 事件D 没有事件与其合并,但还是会继续发送
	
	//2、若在被观察者1 & 被观察者2的事件序列最后发送onComplete()事件,
	//   则被观察者2的事件D也不会发送
	...
});

2)按时间 combineLatest()、combineLatestDelayError()

i.combineLatest()

当两个 Observable 中的任何一个发送了数据后,
将先发送了数据的 Observables 的最新(最后)一个数据 与 另外一个Observable发送的每个数据结合,
最终基于该函数的结果发送数据

与zip()的区别:zip() = 按个数合并,即 1对1 合并;
combineLatest() = 按时间合并,即在同一个时间点上合并

Observable.combineLatest(
		// 第1个发送数据事件的 Observable
              Observable.just(1L, 2L, 3L), 
		// 第2个发送数据事件的Observable:从0开始发送、共发送3个数据、第1次事件延迟发送时间 = 1s、间隔时间 = 1s
              Observable.intervalRange(0, 3, 1, 1, TimeUnit.SECONDS), 
              new BiFunction<Long, Long, Long>() {
			@Override
			public Long apply(Long o1, Long o2) throws Exception {
				// o1 = 第1个 Observable 发送的最新(最后)1个数据
				// o2 = 第2个Observable发送的每1个数据
				Log.e(TAG, "合并的数据是: "+ o1 + " "+ o2);
				return o1 + o2;
				// 合并的逻辑 = 相加
				// 即第1个Observable发送的最后1个数据 与 第2个Observable发送的每1个数据进行相加
			}
      }).subscribe(new Consumer<Long>() {
          @Override
          public void accept(Long s) throws Exception {
		/* 结果:
				合并的数据是:3 0
				合并的结果是:3
				合并的数据是:3 1
				合并的结果是:4
				合并的数据是:3 2
				合并的结果是:5
		 */
              Log.e(TAG, "合并的结果是: "+s);
          }
      });

ii.combineLatestDelayError()
类似于concatDelayError() / mergeDelayError() ,即错误处理。
一个 被观察者的onError()事件,延迟到另一个 被观察者的事件发送完之后再发送。

3)合并成1个事件发送 reduce()、collect()

i.reduce()

把被观察者需要发送的事件聚合成1个事件 & 发送

聚合的逻辑根据需求撰写,但本质都是【前2个数据聚合,然后与后1个数据继续进行聚合】,依次类推

Observable.just(1,2,3,4)
	.reduce(new BiFunction<Integer, Integer, Integer>() {
		// 在该复写方法中复写聚合的逻辑
		@Override
		public Integer apply(@NonNull Integer s1, @NonNull Integer s2) throws Exception {
			Log.e(TAG, "本次计算的数据是: "+s1 +" 乘 "+ s2);
			return s1 * s2;
			// 本次聚合的逻辑是:全部数据相乘起来
			// 原理:第1次取前2个数据相乘,
			//		 之后每次获取到的数据 = 返回的数据x原始下1个数据
		}
	}).subscribe(new Consumer<Integer>() {
		@Override
		public void accept(@NonNull Integer s) throws Exception {
			/*结果:
				本次计算的数据是:1 乘 2
				本次计算的数据是:2 乘 3
				本次计算的数据是:6 乘 4
				最终计算的结果是:24
			*/
			Log.e(TAG, "最终计算的结果是: "+s);
		}
	});

ii.collect()

将被观察者 Observable 发送的数据事件收集到一个数据结构里

Observable.just(1, 2, 3 ,4, 5, 6)
	// 1. 创建数据结构(容器),用于收集被观察者发送的数据
	.collect(new Callable<ArrayList<Integer>>() {
			@Override
			public ArrayList<Integer> call() throws Exception {
				return new ArrayList<>();
			}
			// 2. 对发送的数据进行收集
		}, new BiConsumer<ArrayList<Integer>, Integer>() {
			@Override
			public void accept(ArrayList<Integer> list, Integer integer) throws Exception {
				// 参数说明:list = 容器,integer = 后者数据
				list.add(integer);
				// 对发送的数据进行收集
			}
		}).subscribe(new Consumer<ArrayList<Integer>>() {
			@Override
			public void accept(@NonNull ArrayList<Integer> s) throws Exception {
				Log.e(TAG, "本次发送的数据是: "+s);
				//结果:本次发送的数据是:[1,2,3,4,5,6]
			}
});
3、发送事件前追加发送事件
startWith()/startWithArray()

在一个被观察者发送事件前,追加发送一些数据 / 一个新的被观察者

1)在一个被观察者发送事件前,追加发送一些数据

// 注:追加数据顺序 = 后调用先追加
Observable.just(4, 5, 6)
	  .startWith(0)  // 追加单个数据 = startWith()
	  .startWithArray(1, 2, 3) // 追加多个数据 = startWithArray()
	  .subscribe(new Observer<Integer>() {
		...
		/* 结果:
				接收到了事件 1
				接收到了事件 2
				接收到了事件 3
				接收到了事件 0
				接收到了事件 4
				接收到了事件 5
				接收到了事件 6
		 */
});

2)在一个被观察者发送事件前,追加发送被观察者 & 发送数据

// 注:追加数据顺序 = 后调用先追加
Observable.just(4, 5, 6)
	.startWith(Observable.just(1, 2, 3))
	.subscribe(new Observer<Integer>() {
		...
		/* 结果:
				接收到了事件 1
				接收到了事件 2
				接收到了事件 3
				接收到了事件 4
				接收到了事件 5
				接收到了事件 6
		 */
	});
4、统计发送事件数量

1)count()
统计被观察者【发送事件的数量】

// 注:返回结果 = Long类型
Observable.just(1, 2, 3, 4)
            .count()
            .subscribe(new Consumer<Long>() {
              @Override
              public void accept(Long aLong) throws Exception {
                  Log.e(TAG, "发送的事件数量 =  "+aLong);
			//结果:发送的事件数量 4
              }
          });

五、功能性操作符

1、连接被观察者 & 观察者
	订阅:subscribe()

	//通过订阅(subscribe)连接观察者和被观察者
	observable.subscribe(observer);
2、线程调度
	subscribeOn() 设置被观察者执行的线程
	observeOn()	  设置观察者执行的线程
	
	场景:快速、方便指定 & 控制被观察者 & 观察者 的工作线程
			类型							含义					应用场景
		----------------------------------------------------------------------	
		Schedulers.immediate()		当前线程 = 不指定线程			   默认
		----------------------------------------------------------------------
		AndroidSchedulers.mainThread()	Android主线程				  操作UI
		----------------------------------------------------------------------
		Schedulers.newThread()			 常规新线程					耗时等操作
		----------------------------------------------------------------------
		Schedulers.io()					 io操作线程			网络请求、读写文件等io密集型操作
		----------------------------------------------------------------------
		Schedulers.computation()		CPU计算操作线程				大量计算操作

	RxJava内部使用【线程池】来维护这些线程,所以线程的调度效率非常高。
	
	
	observable.subscribeOn(Schedulers.newThread()) // 1. 指定被观察者 生产事件的线程
              .observeOn(AndroidSchedulers.mainThread())  // 2. 指定观察者 接收 & 响应事件的线程
              .subscribe(observer); // 3. 最后再通过订阅(subscribe)连接观察者和被观察者
3、延迟操作
	delay()
	
	使得被观察者延迟一段时间再发送事件
	
	Observable.just(1, 2, 3)
		.delay(3, TimeUnit.SECONDS) // 延迟3s再发送,由于使用类似,所以此处不作全部展示
		.subscribe(new Observer<Integer>() {
			...
		});
4、在事件的生命周期中操作
	do()
	
	场景:在事件发送 & 接收的整个生命周期过程中进行操作
		  如发送事件前的初始化、发送事件后的回调请求等

	Observable.create(new ObservableOnSubscribe<Integer>() {
			@Override
			public void subscribe(ObservableEmitter<Integer> e) throws Exception {
				e.onNext(1);
				e.onNext(2);
				e.onNext(3);
				e.onError(new Throwable("发生错误了"));
             }
           })
            // 1. 当Observable 每发送1次数据事件,就会调用1次
            .doOnEach(new Consumer<Notification<Integer>>() {
                @Override
                public void accept(Notification<Integer> integerNotification) throws Exception {
                    Log.d(TAG, "doOnEach: " + integerNotification.getValue());
                }
            })
            // 2. 执行Next事件前调用
            .doOnNext(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) throws Exception {
                    Log.d(TAG, "doOnNext: " + integer);
                }
            })
            // 3. 执行Next事件后调用
            .doAfterNext(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) throws Exception {
                    Log.d(TAG, "doAfterNext: " + integer);
                }
            })
            // 4. Observable正常发送事件完毕后调用
            .doOnComplete(new Action() {
                @Override
                public void run() throws Exception {
                    Log.e(TAG, "doOnComplete: ");
                }
            })
            // 5. Observable发送错误事件时调用
            .doOnError(new Consumer<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    Log.d(TAG, "doOnError: " + throwable.getMessage());
                }
            })
            // 6. 观察者订阅时调用
            .doOnSubscribe(new Consumer<Disposable>() {
                @Override
                public void accept(@NonNull Disposable disposable) throws Exception {
                    Log.e(TAG, "doOnSubscribe: ");
                }
            })
            // 7. Observable 发送事件完毕后调用,无论正常发送完毕 / 异常终止
            .doAfterTerminate(new Action() {
                @Override
                public void run() throws Exception {
                    Log.e(TAG, "doAfterTerminate: ");
                }
            })
            // 8. 最后执行
            .doFinally(new Action() {
                @Override
                public void run() throws Exception {
                    Log.e(TAG, "doFinally: ");
                }
            })
            .subscribe(new Observer<Integer>() {
                ...
				/*结果:
						doOnSubscribe
						doOnEach 1
						doOnNext 1
						接收到事件 1
						doAfterNext 1
						doOnEach 2
						doOnNext 2
						接收到事件 2
						doAfterNext 2
						doOnEach 3
						doOnNext 3
						接收到事件 3
						doAfterNext 3
						doOnEach null
						doOnError 发送错误了
						对Error事件做出响应
						doFinally
						doAfterTerminate							
				*/
            });
5、错误处理
	1)onErrorReturn()
		
		发送事件过程中,遇到错误时的处理机制
		可捕获再它之前发生的异常
		
		Observable.create(new ObservableOnSubscribe<Integer>() {
				@Override
				public void subscribe(ObservableEmitter<Integer> e) throws Exception {
					e.onNext(1);
					e.onNext(2);
					e.onError(new Throwable("发生错误了"));
				 }
		   }).onErrorReturn(new Function<Throwable, Integer>() {
				@Override
				public Integer apply(@NonNull Throwable throwable) throws Exception {
					// 捕捉错误异常
					Log.e(TAG, "在onErrorReturn处理了错误: "+throwable.toString() );
					// 发生错误事件后,发送一个"666"事件,最终正常结束
					return 666;						
				}
			})
			.subscribe(new Observer<Integer>() {
				...
			});
	
	2)onErrorResumeNext()
		
		遇到错误时,发送1个新的Observable
		
		onErrorResumeNext() 拦截的错误 = Throwable;若需拦截Exception请用onExceptionResumeNext()
		若 onErrorResumeNext() 拦截的错误 = Exception,则会将错误传递给观察者的 onError 方法

		Observable.create(new ObservableOnSubscribe<Integer>() {
			@Override
			public void subscribe(ObservableEmitter<Integer> e) throws Exception {
				e.onNext(1);
				e.onNext(2);
				e.onError(new Throwable("发生错误了"));
             }
           }).onErrorResumeNext(new Function<Throwable, ObservableSource<? extends Integer>>() {
                @Override
                public ObservableSource<? extends Integer> apply(@NonNull Throwable throwable) throws Exception {
                    // 1. 捕捉错误异常
                    Log.e(TAG, "在onErrorReturn处理了错误: "+throwable.toString() );
                    // 2. 发生错误事件后,发送一个新的被观察者 & 发送事件序列
                    return Observable.just(11,22);                        
                }
            })
            .subscribe(new Observer<Integer>() {
                ...
            });
	
	3)onExceptionResumeNext()
		
		遇到错误时,发送1个新的Observable
		
		onExceptionResumeNext() 拦截的错误 = Exception;若需拦截Throwable请用onErrorResumeNext()
		若onExceptionResumeNext() 拦截的错误 = Throwable,则会将错误传递给观察者的 onError方法

		Observable.create(new ObservableOnSubscribe<Integer>() {
			@Override
			public void subscribe(ObservableEmitter<Integer> e) throws Exception {
				e.onNext(1);
				e.onNext(2);
				e.onError(new Exception("发生错误了"));
             }
           }).onExceptionResumeNext(new Observable<Integer>() {
                @Override
                protected void subscribeActual(Observer<? super Integer> observer) {
                    observer.onNext(11);
                    observer.onNext(22);
                    observer.onComplete();
                }
            })
            .subscribe(new Observer<Integer>() {
                ...
            });
	
	4)retry()
		
		重试,即当出现错误时,让被观察者(Observable)重新发射数据
		
		接收到 onError()时,重新订阅 & 发送事件
		Throwable 和 Exception都可拦截
		
		<-- 1. retry() -->
		// 作用:出现错误时,让被观察者重新发送数据
		// 注:若一直错误,则一直重新发送

		<-- 2. retry(long time) -->
		// 作用:出现错误时,让被观察者重新发送数据(具备重试次数限制)
		// 参数 = 重试次数
		 
		<-- 3. retry(Predicate predicate) -->
		// 作用:出现错误后,判断是否需要重新发送数据(若需要重新发送& 持续遇到错误,则持续重试)
		// 参数 = 判断逻辑

		<-- 4. retry(new BiPredicate<Integer, Throwable>) -->
		// 作用:出现错误后,判断是否需要重新发送数据(若需要重新发送 & 持续遇到错误,则持续重试
		// 参数 =  判断逻辑(传入当前重试次数 & 异常错误信息)

		<-- 5. retry(long time,Predicate predicate) -->
		// 作用:出现错误后,判断是否需要重新发送数据(具备重试次数限制)
		// 参数 = 设置重试次数 & 判断逻辑

		
		// 拦截错误后,判断是否需要重新发送请求
		.retry(new Predicate<Throwable>() {
			@Override
			public boolean test(@NonNull Throwable throwable) throws Exception {
				// 捕获异常
				Log.e(TAG, "retry错误: "+throwable.toString());
				//返回false = 不重新重新发送数据 & 调用观察者的onError结束
				//返回true = 重新发送请求(若持续遇到错误,就持续重新发送)
				return true;
			}
		})
		
		// 拦截错误后,判断是否需要重新发送请求
		.retry(new BiPredicate<Integer, Throwable>() {
			@Override
			public boolean test(@NonNull Integer integer, @NonNull Throwable throwable) throws Exception {
				// 捕获异常
				Log.e(TAG, "异常错误 =  "+throwable.toString());
				// 获取当前重试次数
				Log.e(TAG, "当前重试次数 =  "+integer);
				//返回false = 不重新重新发送数据 & 调用观察者的onError结束
				//返回true = 重新发送请求(若持续遇到错误,就持续重新发送)
				return true;
			}
		})
	
		/* 拦截错误后,判断是否需要重新发送请求
		 * 参数一:重试次数  
		 * 参数二:判断是否需要重新发送数据的逻辑
		 */
		.retry(3, new Predicate<Throwable>() {
			@Override
			public boolean test(@NonNull Throwable throwable) throws Exception {
				// 捕获异常
				Log.e(TAG, "retry错误: "+throwable.toString());

				//返回false = 不重新重新发送数据 & 调用观察者的onError()结束
				//返回true = 重新发送请求(最多重新发送3次)
				return true;
			}
		})
	
	5)retryUntil()
	
		出现错误后,判断是否需要重新发送数据
		
		若需要重新发送 & 持续遇到错误,则持续重试
		作用类似于retry(Predicate predicate)
		
		具体使用类似于retry(Predicate predicate),唯一区别:返回 true 则不重新发送数据事件
	
	6)retryWhen()
		
		遇到错误时,将发生的错误传递给一个新的被观察者(Observable),
		并决定是否需要重新订阅原始被观察者(Observable)& 发送事件
	
		// 遇到 error 事件才会回调
		.retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
			
			@Override
			public ObservableSource<?> apply(@NonNull Observable<Throwable> throwableObservable) throws Exception {
				/*参数 Observable<Throwable> 中的泛型 = 上游操作符抛出的异常,可通过该条件来判断异常的类型
				 *返回 Observable<?> = 新的被观察者 Observable(任意类型)
				 * 
				 *此处有两种情况:
				 *	 1.若 新的被观察者 Observable发送的事件 = Error事件,那么 原始Observable则不重新发送事件:
				 *	 2.若 新的被观察者 Observable发送的事件 = Next事件 ,那么原始的Observable则重新发送事件:
				 */
				return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
					@Override
					public ObservableSource<?> apply(@NonNull Throwable throwable) throws Exception {
						//IOException时,返回onNext(null),原始的Observable 重新发送事件
						if (error instanceof IOException) {
						  return Observable.just(null);
						}
						//其他异常,发送onError()事件,不会再重试
						return Observable.error(error);
					}
				});
			}
		})			
6、重复发送 repeat()、repeatWhen()
	(1).接收到.onCompleted()事件后,触发重新订阅 & 发送
	(2).默认运行在一个新的线程上

	1)repeat()
		
		// 不传入参数 = 重复发送次数 = 无限次
		repeat();
		// 传入参数 = 重复发送次数有限
		repeatWhen(Integer);

		// 具体使用
		Observable.just(1, 2, 3, 4)
            .repeat(3) // 重复创建次数 =- 3次
            .subscribe(new Observer<Integer>() {
                ...
            });

	2)repeatWhen()
		
		有条件地、重复发送 被观察者事件
		
		将原始 Observable 停止发送事件的标识(Complete() /  Error())转换成1个 Object 类型数据
		传递给1个新被观察者(Observable),以此决定是否重新订阅 & 发送原来的 Observable

		若新被观察者(Observable)返回1个 Complete / Error 事件,则不重新订阅 & 发送原来的 Observable
		若新被观察者(Observable)返回其余事件时,则重新订阅 & 发送原来的 Observable

		 Observable.just(1,2,4).repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() {
			
			// 在 Function 函数中,必须对输入的 Observable<Object> 进行处理,
			// 这里我们使用的是 flatMap 操作符接收上游的数据
			@Override
			public ObservableSource<?> apply(@NonNull Observable<Object> objectObservable) throws Exception {
				
				/* 将原始 Observable 停止发送事件的标识(Complete()/Error())转换成1个 Object 类型数据传递给1个新被观察者(Observable)
				 * 以此决定是否重新订阅 & 发送原来的 Observable
				 * 此处有2种情况:
				 * 	1.若新被观察者(Observable)返回1个Complete()/Error()事件,则不重新订阅 & 发送原来的 Observable
				 *  2.若新被观察者(Observable)返回其余事件,则重新订阅 & 发送原来的 Observable
				 */
				return objectObservable.flatMap(new Function<Object, ObservableSource<?>>() {
					@Override
					public ObservableSource<?> apply(@NonNull Object throwable) throws Exception {

						/* 情况1:若新被观察者(Observable)返回1个Complete()/Error()事件,则不重新订阅 & 发送原来的 Observable
						 *
						 * Observable.empty() = 发送Complete事件,但不会回调观察者的onComplete()
						 */
						return Observable.empty();
						
						/* 返回Error事件 = 回调onError()事件,并接收传过去的错误信息。
						 * return Observable.error(new Throwable("不再重新订阅事件"));
						 */

						/* 情况2:若新被观察者(Observable)返回其余事件,则重新订阅 & 发送原来的 Observable
						 * return Observable.just(1);
					     * 仅仅是作为1个触发重新订阅被观察者的通知,发送的是什么数据并不重要,只要不是Complete()/Error()事件
						 */
					}
				});

			}
		})
		.subscribe(new Observer<Integer>() {
			...
		});

		repeat()与retry()区别:
				当.repeat()接收到.onCompleted()事件后触发重订阅。
				当.retry()接收到.onError()事件后触发重订阅。
				
		repeatWhen()与 retryWhen()的区别:
				repeatWhen():若新被观察者(Observable)返回1个Complete()/Error()事件,则不重新订阅 & 发送原来的 Observable
				retryWhen():新的被观察者 Observable发送的事件 = Error事件,那么 原始 Observable 则不重新发送事件:

六、RxJava过滤操作符 filter、ofType、sample、take 等

1、根据 指定条件 过滤事件
	1)filter() 过滤 特定条件的事件
	
		.filter(new Predicate<Integer>() {
			/* 根据test()的返回值 对被观察者发送的事件进行过滤 & 筛选
			 * a. 返回true,则继续发送
			 * b. 返回false,则不发送(即过滤)
			 */
			@Override
			public boolean test(Integer integer) throws Exception {
				return integer > 3;
				// 本例子 = 过滤了整数≤3的事件
			}
		})
		
	2)ofType() 筛选出 特定数据类型的数据
		
		Observable.just(1, "Carson", 3, "Ho", 5)
			.ofType(Integer.class) // 筛选出 整型数据,其他类型的数据会被过滤掉
			.subscribe(new Consumer<Integer>() {
				@Override
				public void accept( Integer integer) throws Exception {
					Log.d(TAG,"获取到的整型事件元素是: "+ integer);
				}
			});
		
	3)skip()/skipLast() 跳过某个事件
		
		// 使用1:根据顺序跳过数据项
		Observable.just(1, 2, 3, 4, 5)
				.skip(1) 	 // 跳过正序的前1项,过滤掉了1
				.skipLast(2) // 跳过正序的后2项,过滤掉了4,5
				.subscribe(new Consumer<Integer>() {
					@Override
					public void accept( Integer integer) throws Exception {
						Log.d(TAG,"获取到的整型事件元素是: "+ integer);
					}
				});

		// 使用2:根据时间跳过数据项
		// 发送事件特点:发送数据,从0开始,共发送5个数据,也就是 0,1,2,3,4
		// 每隔1s发送一次,每次递增1;第1次发送延迟0s
		Observable.intervalRange(0, 5, 0, 1, TimeUnit.SECONDS)
            .skip(1, TimeUnit.SECONDS) // 跳过第1s发送的数据,过滤掉了0
            .skipLast(1, TimeUnit.SECONDS) // 跳过最后1s发送的数据,过滤掉了最后一条数据4
            .subscribe(new Consumer<Long>() {

                @Override
                public void accept( Long along ) throws Exception {
                    Log.d(TAG,"获取到的整型事件元素是: "+ along);
                }
            });
					
	4)distinct()/distinctUntilChanged()
		
		过滤事件序列中重复的事件/连续重复的事件
		
		// 使用1:过滤事件序列中重复的事件
		Observable.just(1, 2, 3, 1 , 2 )
			.distinct()//会过滤掉重复的 1,2
			.subscribe(new Consumer<Integer>() {
				  @Override
				  public void accept( Integer integer) throws Exception {
					  Log.d(TAG,"不重复的整型事件元素是: "+ integer);
					  //结果:1,2,3
				  }
			});

		// 使用2:过滤事件序列中 连续重复的事件
		// 下面序列中,连续重复的事件 = 3、4
		Observable.just(1,2,3,1,2,3,3,4,4 )
            .distinctUntilChanged()//过滤连续重复的3,4;非连续的不会过滤
            .subscribe(new Consumer<Integer>() {
                @Override
                public void accept( Integer integer) throws Exception {
                    Log.d(TAG,"不连续重复的整型事件元素是: "+ integer);
					//结果:1,2,3,1,2,3,4
                }
            });
2、根据 指定事件数量 过滤事件
	场景:通过设置指定的事件数量,仅发送特定数量的事件

	1)take() 指定观察者最多能接收到的事件数量
		
		 // 指定了观察者只能接收2个事件
		observable.take(2)
		
	2)takeLast() 指定观察者只能接收到被观察者发送的最后几个事件
		
		//指定观察者只能接受被观察者发送的最后3个事件
		observable.take(3) 
3、根据 指定时间 过滤事件
	通过设置指定的时间,仅发送在该时间内的事件

	1)throttleFirst()/throttleLast()
		在某段时间内,只发送该段时间内第1次事件 / 最后1次事件
		
		/* 仅发送每1秒中,的第一个事件
		 * 比如,第一秒的第一个事件、第二秒的第一个事件、第三秒的第一个事件。
		 */
		observable.throttleFirst(1, TimeUnit.SECONDS)
		/* 仅发送每1秒中,的最后一个事件
		 * 比如,第一秒的最后一个事件、第二秒的最后一个事件、第三秒的最后一个事件。
		 */
		observable.throttleLast(1, TimeUnit.SECONDS)
	
	2)sample()

		在某段时间内,只发送该段时间内最新(最后)1次事件,与 throttleLast() 操作符类似
		
	3)throttleWithTimeout()/debounce()
		
		发送数据事件时,若2次发送事件的间隔<指定时间,就会丢弃前一次的数据,
		直到指定时间内都没有新数据发射时才会发送后一次的数据
		
		//丢弃间隔小于指定时间1s 的前一次数据
		observable.throttleWithTimeout(1, TimeUnit.SECONDS)
4、根据 指定事件位置 过滤事件
	通过设置指定的位置,过滤在该位置的事件

	1)firstElement()/lastElement()
		
		仅选取第1个元素 / 最后一个元素
		//获取第一个元素
		observable.firstElement() 
		
		//获取最后一个元素
		observable.lastElement()
	
	2)elementAt( index )
		
		指定接收某个元素(通过 索引值 确定),位置索引从0开始
		允许越界,即 获取的位置索引 > 发送事件序列长度
		
		// 使用1:获取位置索引 = 2的 元素
		// 位置索引从0开始
		Observable.just(1, 2, 3, 4, 5)
			.elementAt(2)
			.subscribe(new Consumer<Integer>() {
				@Override
				public void accept( Integer integer) throws Exception {
					Log.d(TAG,"获取到的事件元素是: "+ integer);
				}
			});

		// 使用2:获取的位置索引 > 发送事件序列长度时,设置默认参数
		Observable.just(1, 2, 3, 4, 5)
            .elementAt(6 ,10) //默认值是10,位置6越界,则发送默认值10
            .subscribe(new Consumer<Integer>() {
                @Override
                public void accept( Integer integer) throws Exception {
                    Log.d(TAG,"获取到的事件元素是: "+ integer);
                }
            });
	
	3)elementAtOrError()
	
		在elementAt()的基础上,当出现越界情况(即获取的位置索引 > 发送事件序列长度)时,即抛出异常
		
		越界时,会抛出异常 NoSuchElementException

七、Rxjava背压相关理解

1、背景:观察者 & 被观察者 之间存在2种订阅关系:同步 & 异步。

1)同步订阅:观察者 & 被观察者 工作【在同一线程】
被观察者每次发送1个事件,必须等到观察者接收& 处理后,才能继续发送下一个事件

2)异步订阅:观察者 & 被观察者 工作【在不同线程】

被观察者 不需要 等待观察者接收& 处理后才能继续发送下一个事件,而是不断发送,直到发送事件完毕

但此时的事件并不会直接发送到观察者处,而是先发送到缓存区,等观察者从缓存区取出事件来处理。

被观察者发送事件速度 与 观察者接收事件速度 不匹配的情况。

i.发送 & 接收事件速度 = 单位时间内 发送 & 接收事件的数量

ii.多数情况,主要是 被观察者发送事件速度 > 观察者接收事件速度

问题:
被观察者 发送事件速度太快,而观察者 来不及接收所有事件,
从而导致观察者无法及时响应 / 处理所有发送过来事件的问题,
最终导致缓存区溢出、事件丢失 & OOM

解决方案:
采用背压策略。

2、背压策略

一种 控制事件流速 的策略,对超出缓存区大小的事件进行丢弃、保留、报错的措施。

在【异步订阅关系】中,控制事件发送 & 接收的速度

场景:被观察者发送事件速度 与 观察者接收事件速度 不匹配的场景;比如,网络请求。

3、背压策略的具体实现:Flowable

是RxJava 2.0中被观察者的一种新实现,同时也是背压策略实现的承载者

实现 非阻塞式背压 策略。

4、Flowable 特点

1)对应的观察者变为 Subscriber

2)所有的操作符强制支持背压

3)缓存区存放策略
i. 按发送顺序保存在缓存区,先发送、先进入缓存区
ii. 先进入缓存区的事件先取出
iii. 类似队列,实际上,在zip内部的实现 = 队列

4)默认的缓存区(队列)大小 = 128

5、Flowable的基础使用
	//【步骤1】:创建被观察者 =  Flowable
    Flowable<Integer> upstream = Flowable.create(new FlowableOnSubscribe<Integer>() {
        @Override
        public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
            emitter.onNext(1);
            emitter.onNext(2);
            emitter.onNext(3);
            emitter.onComplete();
        }
    }, BackpressureStrategy.ERROR);
    // 需要传入背压参数BackpressureStrategy,下面会详细讲解

	//【步骤2】:创建观察者 =  Subscriber
    Subscriber<Integer> downstream = new Subscriber<Integer>() {

        @Override
        public void onSubscribe(Subscription s) {
            /* 对比Observer传入的Disposable参数,Subscriber此处传入的参数 = Subscription
             * 相同点:Subscription具备Disposable参数的作用,即Disposable.dispose()切断连接, 
			 *		  同样的调用Subscription.cancel()切断连接
             * 
			 * 不同点:Subscription增加了void request(long n)
			 */
            s.request(Long.MAX_VALUE);// 关于request()下面会继续详细说明
        }
		...
    };

    //【步骤3】:建立订阅关系
    upstream.subscribe(downstream);
6、控制 观察者接收事件 的速度
	1)异步订阅情况
		响应式拉取:观察者根据自身实际情况按需接收事件。
		
		实现方式:【Subscriber.Subscription.request()】
				  通过观察者中的 onSubscribe()的 Subscription 参数的 request()方法控制流速。
				  
		注意:
			异步订阅情况,观察者没有设置 Subscription.request(long n),即说明观察者不接收事件。
			此时被观察者仍能继续发送事件(存放在缓存区),等观察者需要时再取出被观察者事件。
			
			缓存区溢出时,会报错 MissingResourceException。
	
		// 1. 创建被观察者Flowable
		Flowable.create(new FlowableOnSubscribe<Integer>() {
			@Override
			public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
				// 一共发送4个事件
				Log.d(TAG, "发送事件 1");
				emitter.onNext(1);
				Log.d(TAG, "发送事件 2");
				emitter.onNext(2);
				Log.d(TAG, "发送事件 3");
				emitter.onNext(3);
				Log.d(TAG, "发送事件 4");
				emitter.onNext(4);
				Log.d(TAG, "发送完成");
				emitter.onComplete();
			}
		}, BackpressureStrategy.ERROR)
			.subscribeOn(Schedulers.io()) // 设置被观察者在io线程中进行
			.observeOn(AndroidSchedulers.mainThread()) // 设置观察者在主线程中进行
			.subscribe(new Subscriber<Integer>() {
				@Override
				public void onSubscribe(Subscription s) {
					/* 对比Observer传入的Disposable参数,Subscriber此处传入的参数 = Subscription
					 * 相同点:Subscription参数具备Disposable参数的作用,即Disposable.dispose()切断连接, 同样的调用Subscription.cancel()切断连接
					 * 不同点:Subscription增加了void request(long n)
					 */

					/* 作用:决定观察者能够接收多少个事件
					 * 如设置了s.request(3),这就说明观察者能够接收3个事件(多出的事件存放在缓存区)
					 * 官方默认推荐使用Long.MAX_VALUE,即s.request(Long.MAX_VALUE);
					 */
					s.request(3);
				}
				...
			});
	
	2)同步订阅的情况
	
		同步订阅并不会出现被观察者发送事件速度 > 观察者接收事件速度的情况。
		可是,却会出现被观察者发送事件数量 > 观察者接收事件数量的问题。
		
		i. 同步订阅没有缓存区
		ii.被观察者在发送1个事件后,必须等待观察者接收后,才能继续发下1个事件
		
		结论:
			如果观察者没有设置 Subscription.request(long n)
			此时被观察者发送第一个事件,就会抛出 MissingResourceException
7、控制 被观察者发送事件 的速度
	反馈控制:被观察者 根据 观察者的接收事件能力,控制发送事件速度。
	
	实现方式:FlowableEmitter.requested()
			  通过 被观察者中 FlowableEmitter 类的 requested() 方法控制流速。
	
	1)FlowableEmitter类的requested()介绍
		
		public interface FlowableEmitter<T> extends Emitter<T> {
		// FlowableEmitter = 1个接口,继承自Emitter
		// Emitter 接口方法包括:onNext(),onComplete() & onError
			
			/* 作用:返回当前线程中request(a)中的a值
			 * 该 request(a) 则是措施1中讲解的方法,作用 = 设置
			 */
			long requested();			   
			...
		}

	2)每个线程中的 requested()的返回值 = 该线程中的 request(a)的a值
	
	3)反向控制 被观察者发送速度 原理
		
		同步订阅关系:
			i.被观察者 FlowableEmitter.requested()的返回值 = 观察者 Subscription.request(a)的参数值
			
			ii.被观察者通过 FlowableEmitter.requested()的返回值,知道了观察者接收事件的能力,
			   从而根据该信息控制事件发送速度,达到观察者反向控制被观察者的效果。
		
		异步订阅关系:
			i.被观察者 FlowableEmitter.requested() 的返回值,等于
			    被观察者线程中 RxJava内部调用的request(n)的n值。(n=128、96、0)
				从而每次发送128、96、或0个事件给观察者。
			
			ii.观察者requested() 的返回值 = 观察者线程中 request(a)中的参数a值
			
			iii.由于二者处于不同线程,被观察者 无法通过 FlowableEmitter.requested() 知道观察者接收事件的能力
			    只能通过RxJava 内部固定设置,从而反向控制被观察者的发送事件速度。
				
				
		同步订阅控制 被观察者速度 实现:
				Flowable.create(new FlowableOnSubscribe<Integer>() {
					@Override
					public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
						// 调用emitter.requested()获取当前观察者需要接收的事件数量
						long n = emitter.requested();
						Log.d(TAG, "观察者可接收事件" + n);
						// 根据emitter.requested()的值,即当前观察者需要接收的事件数量来发送事件
						for (int i = 0; i < n; i++) {
							Log.d(TAG, "发送了事件" + i);
							emitter.onNext(i);
						}
					}
				}, BackpressureStrategy.ERROR)
				.subscribe(new Subscriber<Integer>() {
					@Override
					public void onSubscribe(Subscription s) {
						Log.d(TAG, "onSubscribe");
						// 设置观察者每次能接受10个事件
						s.request(10);
					}
					...
				});
				
				特别注意 FlowableEmitter.requested():
				
					[a]可叠加性  观察者可连续要求接收事件,被观察者会进行叠加并一起发送。
					
					[b]实时更新性 每次发送事件后, FlowableEmitter.requested()的返回值会实时更新观察者能接收的事件。
						仅计算Next事件,complete & error事件不算
						
					[c]异常 FlowableEmitter.requested()返回值 = 0 时,代表观察者已经不可接收事件。
					   此时,被观察者继续发送事件,会抛出 MissingResourceException。
		
		异步订阅控制 被观察者速度 实现:
				
				Flowable.create(new FlowableOnSubscribe<Integer>() {
					@Override
					public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
						// 调用emitter.requested()获取当前观察者需要接收的事件数量
						Log.d(TAG, "观察者可接收事件数量 = " + emitter.requested());
					}
				}, BackpressureStrategy.ERROR).subscribeOn(Schedulers.io()) //设置被观察者在io线程中进行
						.observeOn(AndroidSchedulers.mainThread()) //设置观察者在主线程中进行
						.subscribe(new Subscriber<Integer>() {
							@Override
							public void onSubscribe(Subscription s) {
								/*
								 * 该设置仅影响 观察者线程中的requested,却不会影响的被观察者中的 FlowableEmitter.requested()的返回值
								 * 因为FlowableEmitter.requested()的返回值 取决于RxJava内部调用request(n),而该内部调用会在一开始就调用 request(128)
								 */
								s.request(150);
							}
							...
						});
8、背压策略模式:BackpressureStrategy
	当缓存区大小存满、被观察者仍然继续发送下1个事件时,该如何处理的策略方式
	
	1)BackpressureStrategy.ERROR 直接抛出 MissingResourceException
	
	2)BackpressureStrategy.MISSING 友好提示:缓冲区满了
	
	3)BackpressureStrategy.BUFFER 将缓存区大小设置成无限大
	
	4)BackpressureStrategy.DROP 超过缓存区大小(128) 的事件不再接收,丢弃
	
	5)BackpressureStrategy.LATEST 只保存最新(最后事件),超过缓存区大小的事件丢弃
9、注意事项
	FLowable 可通过自己创建(如上面例子),或通过其他方式自动创建,如 interval()操作符
	
	1)对于自身手动创建FLowable的情况,可通过传入背压模式参数选择背压策略
	
	2)可是对于自动创建FLowable,却无法手动传入传入背压模式参数,
	  那么出现流速不匹配的情况下,该如何选择 背压模式呢?
		
		解决方案:
			RxJava 2.0内部提供 封装了背压策略模式的方法,默认采用BackpressureStrategy.ERROR模式
			
			onBackpressureBuffer()
			onBackpressureDrop()
			onBackpressureLatest()
			
			Flowable.interval(1, TimeUnit.MILLISECONDS)
				// 添加背压策略封装好的方法,此处选择Buffer模式,即缓存区大小无限制
				.onBackpressureBuffer() 
				.observeOn(Schedulers.newThread()) 
				.subscribe(new Subscriber<Long>() {
					@Override
					public void onSubscribe(Subscription s) {
						Log.d(TAG, "onSubscribe");
						mSubscription = s;
						s.request(Long.MAX_VALUE); 
					}
					...
				});

推荐阅读:

Android Rxjava:这是一篇 清晰 & 易懂的Rxjava 入门教程 https://www.jianshu.com/p/a406b94f3188

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值