RxJava默认的发送事件与接收事件均与当前线程在同一个线程。切换线程就需要使用到Schedulers/AndroidSchedulers进行切换。
简单的来说, subscribeOn() 指定的是上游发送事件的线程, observeOn() 指定的是下游接收事件的线程。
//设置上游发送事件在新的子线程,下游接受事件在主线程
observable.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
多次指定上游的线程只有第一次指定的有效, 也就是说多次调用subscribeOn() 只有第一次的有效, 其余的会被忽略。
多次指定下游的线程是可以的, 也就是说每调用一次observeOn() , 下游的线程就会切换一次。
在RxJava中, 已经内置了很多线程选项供我们选择, 例如有
-
Schedulers.io()
代表io操作的线程, 通常用于网络,读写文件等io密集型的操作
-
Schedulers.computation()
代表CPU计算密集型的操作, 例如需要大量计算的操作
-
Schedulers.newThread()
代表一个常规的新线程
-
AndroidSchedulers.mainThread()
代表Android的主线程
当上下游工作在同一个线程中时, 这时候是一个同步的订阅关系, 也就是说上游每发送一个事件必须等到下游接收处理完了以后才能接着发送下一个事件。
当上下游工作在不同的线程中时, 这时候是一个异步的订阅关系, 这个时候上游发送数据不需要等待下游接收, 为什么呢?
因为两个线程并不能直接进行通信, 因此上游发送的事件并不能直接到下游里去, 这个时候就 上游把事件发送到一个水缸里去,暂时存储起来, 下游从水缸里取出事件来处理, 因此, 当上游发事件的速度太快, 下游取事件的速度太慢, 水缸就会迅速装满, 然后溢出来, 最后就OOM了。
这个水缸的最大默认可接受128个事件,不过水缸只有在上下游不在同一个线程中才能使用。