1. RxJava详解(基于1.X版本)
https://blog.youkuaiyun.com/weixin_37730482/article/details/68059274
2.RxJava详解(基于2.X版本)
https://blog.youkuaiyun.com/weixin_37730482/article/details/69280013
本章节继续讲解RxJava的使用
Gradle依赖 RxJava&RxAndroid 版本须一致 即都是2.x版本
implementation 'io.reactivex.rxjava2:rxjava:2.0.1'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
一.RxJava基于事件流的链式调用
上述讲解RxJava的使用时,观察者和被观察者的创建是分开的。其实两者可以合并在一起使用。这样代码看起来更加简洁。这就是RxJava基于事件流的链式调用。
1.代码(单个订阅关系)
package com.example.rxjava20;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
public class MainActivity extends AppCompatActivity {
private Disposable mDisposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
method1();
}
/**
* RxJava基于事件流的链式调用
* create操作符创建被观察者 最常用
*/
public void method1() {
Observable.create(new ObservableOnSubscribe<Object>() {
@Override
public void subscribe(ObservableEmitter<Object> e) throws Exception {
if (e == null) {
return;
}
//没有切断与观察者的关联
if (!e.isDisposed()) {
e.onNext("被观察者对象 发出第1波数据......");
e.onNext("被观察者对象 发出第2波数据......");
e.onNext("被观察者对象 发出第3波数据......");
e.onComplete();
}
}
}).subscribe(new Observer<Object>() {
@Override
public void onSubscribe(Disposable d) {
if (null == d) {
return;
}
mDisposable = d;
Log.d("TAG", "RxJava链式调用1 观察者 onSubscribe方法执行 是否断开连接----:" + d.isDisposed());
}
@Override
public void onNext(Object value) {
Log.d("TAG", "RxJava链式调用1 观察者 onNext方法执行!!!结果:" + value.toString());
}
@Override
public void onError(Throwable e) {
Log.d("TAG", "RxJava链式调用1 观察者 onError方法执行!!!");
}
@Override
public void onComplete() {
Log.d("TAG", "RxJava链式调用1 观察者 onComplete方法执行!!!");
}
});
}
/**
* onDestroy方法
*/
@Override
protected void onDestroy() {
super.onDestroy();
if (null != mDisposable) {
Log.d("TAG", "onDestroy方法 执行时是否断开----:" + mDisposable.isDisposed());
if (!mDisposable.isDisposed()) {//没有断开
mDisposable.dispose();//断开
Log.d("TAG", "onDestroy方法 断开订阅");
}
}
}
}
结果
D/TAG: RxJava链式调用1 观察者 onSubscribe方法执行 是否断开连接----:false
D/TAG: RxJava链式调用1 观察者 onNext方法执行!!!结果:被观察者对象 发出第1波数据......
D/TAG: RxJava链式调用1 观察者 onNext方法执行!!!结果:被观察者对象 发出第2波数据......
D/TAG: RxJava链式调用1 观察者 onNext方法执行!!!结果:被观察者对象 发出第3波数据......
D/TAG: RxJava链式调用1 观察者 onComplete方法执行!!!
关闭页面
D/TAG: onDestroy方法 执行时是否断开----:true
2.代码(多个订阅关系)
package com.example.rxjava20;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
public class MainActivity extends AppCompatActivity {
private CompositeDisposable mCompositeDisposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCompositeDisposable = new CompositeDisposable();
method1();
method2();
method3();
method4();
}
/**
* RxJava基于事件流的链式调用
* create操作符创建被观察者 最常用
*/
public void method1() {
Observable.create(new ObservableOnSubscribe<Object>() {
@Override
public void subscribe(ObservableEmitter<Object> e) throws Exception {
if (e == null) {
return;
}
//没有切断与观察者的关联
if (!e.isDisposed()) {
e.onNext("被观察者对象 发出第1波数据......");
e.onNext("被观察者对象 发出第2波数据......");
e.onNext("被观察者对象 发出第3波数据......");
e.onComplete();
}
}
}).subscribe(new Observer<Object>() {
@Override
public void onSubscribe(Disposable d) {
if (null == d) {
return;
}
mCompositeDisposable.add(d);
Log.d("TAG", "RxJava链式调用1 观察者 onSubscribe方法执行 是否断开连接----:" + d.isDisposed());
}
@Override
public void onNext(Object value) {
Log.d("TAG", "RxJava链式调用1 观察者 onNext方法执行!!!结果:" + value.toString());
}
@Override
public void onError(Throwable e) {
Log.d("TAG", "RxJava链式调用1 观察者 onError方法执行!!!");
}
@Override
public void onComplete() {
Log.d("TAG", "RxJava链式调用1 观察者 onComplete方法执行!!!");
}
});
}
/**
* RxJava基于事件流的链式调用
* Just操作符创建被观察者 发送的数据格式不统一 Int类型 String类型...
*/
public void method2() {
Observable.just("1", 23, "张三").subscribe(new Observer<Object>() {
@Override
public void onSubscribe(Disposable d) {
if (null == d) {
return;
}
mCompositeDisposable.add(d);
Log.d("TAG", "RxJava链式调用2 观察者 onSubscribe方法执行 是否断开连接----:" + d.isDisposed());
}
@Override
public void onNext(Object value) {
Log.d("TAG", "RxJava链式调用2 观察者 onNext方法执行!!!结果:" + value.toString());
}
@Override
public void onError(Throwable e) {
Log.d("TAG", "RxJava链式调用2 观察者 onError方法执行!!!");
}
@Override
public void onComplete() {
Log.d("TAG", "RxJava链式调用2 观察者 onComplete方法执行!!!");
}
});
}
/**
* RxJava基于事件流的链式调用
* fromArray操作符创建被观察者 发送的数据为数组
*/
public void method3() {
String string[] = new String[]{"123", "fromArray操作符", "李四"};
Observable.fromArray(string).subscribe(new Observer<Object>() {
@Override
public void onSubscribe(Disposable d) {
if (null == d) {
return;
}
mCompositeDisposable.add(d);
Log.d("TAG", "RxJava链式调用3 观察者 onSubscribe方法执行 是否断开连接----:" + d.isDisposed());
}
@Override
public void onNext(Object value) {
Log.d("TAG", "RxJava链式调用3 观察者 onNext方法执行!!!结果:" + value.toString());
}
@Override
public void onError(Throwable e) {
Log.d("TAG", "RxJava链式调用3 观察者 onError方法执行!!!");
}
@Override
public void onComplete() {
Log.d("TAG", "RxJava链式调用3 观察者 onComplete方法执行!!!");
}
});
}
/**
* RxJava基于事件流的链式调用
* fromArray操作符创建被观察者 发送的数据为集合
*/
public void method4() {
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("张三");
list.add("6598");
list.add("我是集合");
Observable.fromIterable(list).subscribe(new Observer<Object>() {
@Override
public void onSubscribe(Disposable d) {
if (null == d) {
return;
}
mCompositeDisposable.add(d);
Log.d("TAG", "RxJava链式调用4 观察者 onSubscribe方法执行 是否断开连接----:" + d.isDisposed());
}
@Override
public void onNext(Object value) {
Log.d("TAG", "RxJava链式调用4 观察者 onNext方法执行!!!结果:" + value.toString());
}
@Override
public void onError(Throwable e) {
Log.d("TAG", "RxJava链式调用4 观察者 onError方法执行!!!");
}
@Override
public void onComplete() {
Log.d("TAG", "RxJava链式调用4 观察者 onComplete方法执行!!!");
}
});
}
/**
* onDestroy方法
*/
@Override
protected void onDestroy() {
super.onDestroy();
if (null != mCompositeDisposable) {
Log.d("TAG", "onDestroy方法 执行时是否断开----:" + mCompositeDisposable.isDisposed());
if (!mCompositeDisposable.isDisposed()) {//没有断开
mCompositeDisposable.dispose();//断开
Log.d("TAG", "onDestroy方法 断开订阅");
}
}
}
}
结果
D/TAG: RxJava链式调用1 观察者 onSubscribe方法执行 是否断开连接----:false
D/TAG: RxJava链式调用1 观察者 onNext方法执行!!!结果:被观察者对象 发出第1波数据......
D/TAG: RxJava链式调用1 观察者 onNext方法执行!!!结果:被观察者对象 发出第2波数据......
D/TAG: RxJava链式调用1 观察者 onNext方法执行!!!结果:被观察者对象 发出第3波数据......
D/TAG: RxJava链式调用1 观察者 onComplete方法执行!!!
D/TAG: RxJava链式调用2 观察者 onSubscribe方法执行 是否断开连接----:false
D/TAG: RxJava链式调用2 观察者 onNext方法执行!!!结果:1
D/TAG: RxJava链式调用2 观察者 onNext方法执行!!!结果:23
D/TAG: RxJava链式调用2 观察者 onNext方法执行!!!结果:张三
D/TAG: RxJava链式调用2 观察者 onComplete方法执行!!!
D/TAG: RxJava链式调用3 观察者 onSubscribe方法执行 是否断开连接----:false
D/TAG: RxJava链式调用3 观察者 onNext方法执行!!!结果:123
D/TAG: RxJava链式调用3 观察者 onNext方法执行!!!结果:fromArray操作符
D/TAG: RxJava链式调用3 观察者 onNext方法执行!!!结果:李四
D/TAG: RxJava链式调用3 观察者 onComplete方法执行!!!
D/TAG: RxJava链式调用4 观察者 onSubscribe方法执行 是否断开连接----:false
D/TAG: RxJava链式调用4 观察者 onNext方法执行!!!结果:1
D/TAG: RxJava链式调用4 观察者 onNext方法执行!!!结果:2
D/TAG: RxJava链式调用4 观察者 onNext方法执行!!!结果:张三
D/TAG: RxJava链式调用4 观察者 onNext方法执行!!!结果:6598
D/TAG: RxJava链式调用4 观察者 onNext方法执行!!!结果:我是集合
D/TAG: RxJava链式调用4 观察者 onComplete方法执行!!!
关闭页面
D/TAG: onDestroy方法 执行时是否断开----:false
D/TAG: onDestroy方法 断开订阅
3.说明
<1> 正如上面demo中的样子,创建出 Observable(被观察者) 和 Observer(观察者),再用 subscribe() 方法将它们订阅,一次 RxJava 的基本使用就完成了。非常简单。这就是RxJava基于事件流的链式调用。
<2> 正如前一章节所述。单个订阅关系时 被观察者使用Create操作符时,订阅关系会自动断开。无论是前一章节讲述的分开创建观察者和被观察者还是此章节讲述的链式调用。但是使用其他的操作符时不会自动断开。
<3> 但是多个订阅关系时,无论是使用什么操作符,无论是前一章节讲述的分开创建观察者和被观察者还是此章节讲述的链式调用。订阅关系都不会自动断开。不过这个情况比较少见。
二.RxJava线程切换
在 RxJava 的默认规则中,事件的发出和消费都是在同一个线程的。也就是说,如果只用上面的方法,实现出来的只是一个同步的观察者模式。
观察者模式本身的目的就是『后台处理,前台回调』的异步机制,因此异步对于 RxJava 是至关重要的。而要实现异步,则需要用到 RxJava 的另一个概念: Scheduler 。
1.默认情况
在 RxJava 的默认规则中,事件的发出和消费都是在同一个线程的。
代码
package com.example.rxjava20;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
public class MainActivity extends AppCompatActivity {
private Disposable disposable;
private Observer observer = null;
private Observable observable = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createObserverMethod();//创建观察者对象
createObservableMethod();//创建被观察者对象
if (null != observer && null != observable) {
observable.subscribe(observer);//完成订阅
}
}
/**
* 创建 观察者对象
*/
public void createObserverMethod() {
observer = new Observer() {
@Override
public void onSubscribe(Disposable d) {
if (null == d) {
return;
}
disposable = d;
Log.d("TAG", "观察者对象 onSubscribe方法 接收数据 是否断开连接----:" + disposable.isDisposed());
Log.d("TAG", "观察者对象 onSubscribe方法 接收数据 线程----:" + Thread.currentThread().getName());
}
@Override
public void onNext(Object value) {
Log.d("TAG", "观察者对象 onNext方法 接收数据 结果:" + value.toString());
Log.d("TAG", "观察者对象 onNext方法 接收数据 线程----:" + Thread.currentThread().getName());
}
@Override
public void onError(Throwable e) {
Log.d("TAG", "观察者对象 onError方法 接收数据 线程----:" + Thread.currentThread().getName());
}
@Override
public void onComplete() {
Log.d("TAG", "观察者对象 onComplete方法 接收数据 线程----:" + Thread.currentThread().getName());
}
};
}
/**
* 创建 被观察者对象
*/
public void createObservableMethod() {
observable = Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter e) throws Exception {
if (e == null) {
return;
}
//没有切断与观察者的关联
if (!e.isDisposed()) {
e.onNext("被观察者对象发出第N波数据......");
e.onComplete();
}
Log.d("TAG", "被观察者对象 发送数据 线程----:" + Thread.currentThread().getName());
}
});
}
/**
* onDestroy方法
*/
@Override
protected void onDestroy() {
super.onDestroy();
if (null != disposable) {
Log.d("TAG", "onDestroy方法 执行时是否断开----:" + disposable.isDisposed());
if (!disposable.isDisposed()) {//没有断开
disposable.dispose();//断开
Log.d("TAG", "onDestroy方法 断开订阅");
}
}
}
}
结果
D/TAG: 观察者对象 onSubscribe方法 接收数据 是否断开连接----:false
D/TAG: 观察者对象 onSubscribe方法 接收数据 线程----:main
D/TAG: 观察者对象 onNext方法 接收数据 结果:被观察者对象发出第N波数据......
D/TAG: 观察者对象 onNext方法 接收数据 线程----:main
D/TAG: 观察者对象 onComplete方法 接收数据 线程----:main
D/TAG: 被观察者对象 发送数据 线程----:main
关闭页面
D/TAG: onDestroy方法 执行时是否断开----:true
验证的结论就是:
在 RxJava 的默认规则中,事件的发出和消费都是在同一个线程的。这显然不是我们要的。
因为我们希望:
<1> 被观察者 (Observable) 在 子线程 中生产事件(如实现耗时操作/IO操作/CPU大量计算等等)。
<2> 观察者(Observer)在 主线程 中接收事件(即实现UI操作)。
所以:
为了解决上述冲突,即实现 真正的异步操作,我们需要对RxJava进行 线程控制(也称为调度 / 切换)。
2.线程切换
<1> 简介
采用 RxJava内置的线程调度器( Scheduler ),即通过 功能性操作符 subscribeOn() observeOn() 实现。
<2> 作用
线程控制,即指定 被观察者 (Observable)
/ 观察者(Observer)
的工作线程类型。
<3> 线程类型
在 RxJava中,内置了多种用于调度的线程类型
类型 | 含义 | 应用场景 |
Schedulers.immediate() | 不指定线程 | 默认 |
Schedulers.newThread() | 开启新线程 | 耗时等操作 |
Schedulers.io() | io操作线程 | 网络请求、读写文件等io密集型操作 |
Schedulers.computation() | CPU计算操作线程 | 大量计算操作 比如图片压缩取样、大量数据的Json解析等CPU密集型计算 |
AndroidSchedulers.mainThread() | Android主线程 | 操作UI |
<4> 修改上述代码
即 修改 观察者和被观察者的订阅关系代码
if (null != observer && null != observable) {
observable.subscribeOn(Schedulers.newThread()) //指定被观察者 生产事件的线程
.observeOn(AndroidSchedulers.mainThread()) //指定观察者 接收 & 响应事件的线程
.subscribe(observer); //最后再通过订阅(subscribe)连接观察者和被观察者
}
<5> 结果
D/TAG: 观察者对象 onSubscribe方法 接收数据 是否断开连接----:false
D/TAG: 观察者对象 onSubscribe方法 接收数据 线程----:main
D/TAG: 观察者对象 onNext方法 接收数据 结果:被观察者对象发出第N波数据......
D/TAG: 观察者对象 onNext方法 接收数据 线程----:main
D/TAG: 观察者对象 onComplete方法 接收数据 线程----:main
D/TAG: 被观察者对象 发送数据 线程----:RxNewThreadScheduler-1
<6> 结论
观察者在UI线程接收数据,被观察者在子线程发送数据。
<7> 再举例 使用Schedulers.io() 一般进行网络请求
if (null != observer && null != observable) {
observable.subscribeOn(Schedulers.io()) //指定被观察者 生产事件的线程
.observeOn(AndroidSchedulers.mainThread()) //指定观察者 接收 & 响应事件的线程
.subscribe(observer); //最后再通过订阅(subscribe)连接观察者和被观察者
}
结果
D/TAG: 观察者对象 onSubscribe方法 接收数据 是否断开连接----:false
D/TAG: 观察者对象 onSubscribe方法 接收数据 线程----:main
D/TAG: 观察者对象 onNext方法 接收数据 结果:被观察者对象发出第N波数据......
D/TAG: 观察者对象 onNext方法 接收数据 线程----:main
D/TAG: 观察者对象 onComplete方法 接收数据 线程----:main
D/TAG: 被观察者对象 发送数据 线程----:RxCachedThreadScheduler-1
<8> 注意
(1) Observable.subscribeOn(XXX) 多次执行 即多次指定被观察者所在的线程。以第一次为准。
代码
if (null != mSubscriber && null != observable) {
observable.subscribeOn(Schedulers.io()) //第一次 指定被观察者 生产事件的线程 IO
.subscribeOn(Schedulers.newThread())//第二次 指定被观察者 生产事件的线程 新线程
.observeOn(AndroidSchedulers.mainThread()) //指定观察者 接收 & 响应事件的线程
.subscribe(mSubscriber); //最后再通过订阅(subscribe)连接观察者和被观察者
}
结果 IO线程
D/TAG: 被观察者 发送数据 线程----:RxIoScheduler-2
D/TAG: 观察者 onNext方法 线程----:main
D/TAG: 观察者 onCompleted方法 线程----:main
(2) Observable.observeOn(XXX) 执行多次 即多次指定观察者所在的线程 每调用一次,观察者的线程就会切换一次。以最后一次为准。
<9> RxJava&RxAndroid线程问题具体使用
Android 网络系列:https://blog.youkuaiyun.com/weixin_37730482/category_6875815.html
三.RxJava线程切换原理
上述讲述了RxJava观察者和被观察者默认所处的线程以及手动指定观察者和被观察者所在的线程。那么线程切换的原理是什么呢?
1.先来看两段代码
代码1
package com.example.rxjava20;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testMethod();
}
private void testMethod() {
Log.d("TAG", "Thread run() 所在线程为 :" + Thread.currentThread().getName());
Observable
.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
Log.d("TAG", "被观察者 subscribe()方法 所在线程为 :" + Thread.currentThread().getName());
emitter.onNext("111111");
emitter.onComplete();
}
})
.subscribeOn(Schedulers.io())//指定被观察者所在的线程 IO线程
.observeOn(AndroidSchedulers.mainThread())//指定观察者所在的线程 UI线程
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.d("TAG", "观察者 onSubscribe()方法 所在线程为 :" + Thread.currentThread().getName());
}
@Override
public void onNext(String s) {
Log.d("TAG", "观察者 onNext()方法 所在线程为 :" + Thread.currentThread().getName());
}
@Override
public void onError(Throwable e) {
Log.d("TAG", "观察者 onError()方法 所在线程为 :" + Thread.currentThread().getName());
}
@Override
public void onComplete() {
Log.d("TAG", "观察者 onComplete()方法 所在线程为 :" + Thread.currentThread().getName());
}
});
}
}
结果1
D/TAG: Thread run() 所在线程为 :main
D/TAG: 观察者 onSubscribe()方法 所在线程为 :main
D/TAG: 被观察者 subscribe()方法 所在线程为 :RxCachedThreadScheduler-1
D/TAG: 观察者 onNext()方法 所在线程为 :main
D/TAG: 观察者 onComplete()方法 所在线程为 :main
结论1
默认情况下 即观察者和被观察者订阅的方法运行在UI线程
观察者的四个方法onSubscribe()方法+onNext()方法+onComplete()方法(onError方法)都运行在observeOn(AndroidSchedulers.mainThread());指定观察者所在的线程中。
被观察者的subscribe方法即发送事件的方法运行在subscribeOn(Schedulers.io())//指定被观察者所在的线程中。
代码2
new Thread(new Runnable() {
@Override
public void run() {
testMethod();
}
}).start();
即 修改上述testMethod()方法所在的线程。
结果2
D/TAG: Thread run() 所在线程为 :Thread-6
D/TAG: 观察者 onSubscribe()方法 所在线程为 :Thread-6
D/TAG: 被观察者 subscribe()方法 所在线程为 :RxCachedThreadScheduler-1
D/TAG: 观察者 onNext()方法 所在线程为 :main
D/TAG: 观察者 onComplete()方法 所在线程为 :main
结论2
这种情况 即观察者和被观察者订阅的方法运行在新线程
观察者的三个方法onNext()方法+onComplete()方法(onError方法)都运行在.observeOn(AndroidSchedulers.mainThread());指定观察者所在的线程中。
观察者onSubscribe()方法运行在当前线程中。
被观察者的subscribe方法即发送事件的方法运行在.subscribeOn(Schedulers.io())//指定被观察者所在的线程中。
综上所述
observeOn()方法:指定观察者所在的线程。onSubscribe()方法除外。onSubscribe()方法所在的线程与当前线程一致。
subscribeOn()方法:指定被观察者所在的线程。
2.源码分析
首先 subscribeOn方法 指定被观察者所在的线程
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> subscribeOn(Scheduler scheduler) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}
第一行代码可以忽略,我们直接看第二行代码。
第二行代码
RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
Function<? super Observable, ? extends Observable> f = onObservableAssembly;
if (f != null) {
return apply(f, source);
}
return source;
}
这个方法就是操作了Observable<T> source这个参数。显然最重要的是new ObservableSubscribeOn<T>(this, scheduler)。
ObservableSubscribeOn类源码
public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
final Scheduler scheduler;
public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
super(source);
this.scheduler = scheduler;
}
@Override
public void subscribeActual(final Observer<? super T> s) {
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
s.onSubscribe(parent);
parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
@Override
public void run() {
source.subscribe(parent);
}
}));
}
...
}
可见,在subscribeActual方法中。调用了
source.subscribe(parent);
也就是说,ObservableSubscribeOn类中的subscribeActual方法中调用了被观察者的subscribe方法。也就是说被观察者的subscribe()方法所在的线程是在这个方法中确定的。
parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
@Override
public void run() {
source.subscribe(parent);
}
}));
调用了Scheduler类的scheduler对象的scheduleDirect方法。也就是说scheduler对象的线程决定了被观察者的subscribe方法所在的线程。scheduler对象的线程也就是subscribeOn()方法传过来的RxJava线程调度类的对象。这里就是subscribeOn(Schedulers.io())。
再来看observeOn()方法 指定观察者所在的线程
public final Observable<T> observeOn(Scheduler scheduler) {
return observeOn(scheduler, false, bufferSize());
}
observeOn方法中第一个参数就是传入的线程,第三个参数是缓存大小。
先看缓存大小
public static int bufferSize() {
return Flowable.bufferSize();
}
public static int bufferSize() {
return BUFFER_SIZE;
}
public abstract class Flowable<T> implements Publisher<T> {
/** The default buffer size. */
static final int BUFFER_SIZE;
static {
BUFFER_SIZE = Math.max(16, Integer.getInteger("rx2.buffer-size", 128));
}
...
}
缓存就是16和128的最大值。
再看observeOn方法
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
ObjectHelper.verifyPositive(bufferSize, "bufferSize");
return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
}
同理,忽略前两行代码直接看第三行。也有一个new对象。ObservableObserveOn对象。
ObservableObserveOn类源码
public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> {
final Scheduler scheduler;
final boolean delayError;
final int bufferSize;
public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) {
super(source);
this.scheduler = scheduler;
this.delayError = delayError;
this.bufferSize = bufferSize;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
Scheduler.Worker w = scheduler.createWorker();
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
}
}
static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>
implements Observer<T>, Runnable {
private static final long serialVersionUID = 6576896619930983584L;
final Observer<? super T> actual;
final Scheduler.Worker worker;
final boolean delayError;
final int bufferSize;
...
}
...
}
该类中。有观察者的四个方法。
onSubscribe方法
@Override
public void onSubscribe(Disposable s) {
if (DisposableHelper.validate(this.s, s)) {
this.s = s;
if (s instanceof QueueDisposable) {
@SuppressWarnings("unchecked")
QueueDisposable<T> qd = (QueueDisposable<T>) s;
int m = qd.requestFusion(QueueDisposable.ANY | QueueDisposable.BOUNDARY);
if (m == QueueDisposable.SYNC) {
sourceMode = m;
queue = qd;
done = true;
actual.onSubscribe(this);
schedule();
return;
}
if (m == QueueDisposable.ASYNC) {
sourceMode = m;
queue = qd;
actual.onSubscribe(this);
return;
}
}
queue = new SpscLinkedArrayQueue<T>(bufferSize);
actual.onSubscribe(this);
}
}
onNext方法
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != QueueDisposable.ASYNC) {
queue.offer(t);
}
schedule();
}
onError方法
@Override
public void onError(Throwable t) {
if (done) {
RxJavaPlugins.onError(t);
return;
}
error = t;
done = true;
schedule();
}
onComplete方法
@Override
public void onComplete() {
if (done) {
return;
}
done = true;
schedule();
}
可以看出,onNext+onError+onComplete方法中,都有schedule方法。但是onSubscribe方法中没有schedule方法。schedule方法就是用来切换线程的。
schedule方法源码
void schedule() {
if (getAndIncrement() == 0) {
worker.schedule(this);
}
}
可以看出worker切换线程,而worker就是上面的构造方法传过来的
final Scheduler.Worker worker;
构造方法
ObserveOnObserver(Observer<? super T> actual, Scheduler.Worker worker, boolean delayError, int bufferSize) {
this.actual = actual;
this.worker = worker;
this.delayError = delayError;
this.bufferSize = bufferSize;
}
也就是new这个类的时候传过来的。
return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
new这个类的地方就是observeOn方法,即设置观察者所在的线程的方法
observeOn(AndroidSchedulers.mainThread())//指定观察者所在的线程 UI线程
这样就能解析,观察者四个方法所在的线程切换的原理了。
四.RxJava线程切换在Android中的运用
Android项目中,经常会遇到线程切换的问题,比如网络请求(IO线程)后需要切换线程在UI线程中更新View。比如在一个数据库操作(IO线程)后需要切换线程在UI线程中更新View。等等。这个时候如果在Activity中可以使用Activity的runOnUiThread()。
Activity的runOnUiThread()方法源码
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
解释:
当前线程不是UI线程,使用Handler切换到主线程。
当前线程是UI线程,则直接run传入的Runnable对象。
那么如果需要切换线程的类不是在Activity中,或者获取Activity不是很方便的时候,怎么切换线程呢?
你可能会这样操作
Handler handler=new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
}
});
但是这样new一个Handler,最好有地方销毁他。如果没有一个地方销毁他,可能会造成内存泄漏。那么有没有其他的办法呢?
如果项目中引入了RxJava和RxAndroid的话,可以使用他们来解决
代码
package com.wjn.rxdemo.rxjava;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import com.wjn.rxdemo.R;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
public class RxJavaActivity extends AppCompatActivity {
private Disposable mDisposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rxjava);
new Thread(new Runnable() {
@Override
public void run() {
Log.d("TAG", "当前线程:" + Thread.currentThread().getName());
runAndroidUI(new Runnable() {
@Override
public void run() {
Log.d("TAG", "被观察者执行线程:" + Thread.currentThread().getName());
}
});
}
}).start();
}
/**
* RxJava 切换Android主线程
*/
private void runAndroidUI(Runnable runnable) {
if (null == runnable) return;
Observable
.empty()//empty操作符 创建一个不发射任何数据但是正常终止的Observable(被观察者)
.observeOn(AndroidSchedulers.mainThread())//指定观察者所在线程
.doOnSubscribe(disposable -> mDisposable = disposable)//观察者订阅时调用
.doOnComplete(() -> {//empty操作符 发送的被观察者 只会在观察者的onComplete方法接收
runnable.run();
if (null != mDisposable) {
boolean b = mDisposable.isDisposed();
Log.d("TAG", "是否取消订阅:" + b);
if (!b) {
mDisposable.dispose();
Log.d("TAG", "线程切换后取消订阅关系");
}
}
})
.subscribe();//订阅
}
/**
* onDestroy方法 取消订阅
*/
@Override
protected void onDestroy() {
super.onDestroy();
boolean b = mDisposable.isDisposed();
Log.d("TAG", "关闭页面时是否取消订阅:" + b);
}
}
结果
D/TAG: 当前线程:Thread-3
D/TAG: 被观察者执行线程:main
D/TAG: 是否取消订阅:false
D/TAG: 线程切换后取消订阅关系
D/TAG: 关闭页面时是否取消订阅:true
如果切换线程时,需要延时XX后执行呢?
代码
package com.wjn.rxdemo.rxjava;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import com.wjn.rxdemo.R;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
public class RxJavaActivity extends AppCompatActivity {
private Disposable mDisposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rxjava);
new Thread(new Runnable() {
@Override
public void run() {
Log.d("TAG", "当前线程:" + Thread.currentThread().getName());
runAndroidUI(new Runnable() {
@Override
public void run() {
Log.d("TAG", "被观察者执行线程:" + Thread.currentThread().getName());
}
}, 5);
}
}).start();
}
/**
* RxJava 切换Android主线程
*/
private void runAndroidUI(Runnable runnable, int time) {
if (null == runnable) return;
Observable
.timer(time, TimeUnit.SECONDS)//timer操作符 延时time(第二个参数是延时单位)发射Observable(被观察者)
.observeOn(AndroidSchedulers.mainThread())//指定观察者所在线程
.doOnSubscribe(disposable -> mDisposable = disposable)//观察者订阅时调用
.doOnComplete(() -> {//在观察者的onComplete方法接收
runnable.run();
if (null != mDisposable) {
boolean b = mDisposable.isDisposed();
Log.d("TAG", "是否取消订阅:" + b);
if (!b) {
mDisposable.dispose();
Log.d("TAG", "线程切换后取消订阅关系");
}
}
})
.subscribe();//订阅
}
/**
* onDestroy方法 取消订阅
*/
@Override
protected void onDestroy() {
super.onDestroy();
boolean b = mDisposable.isDisposed();
Log.d("TAG", "关闭页面时是否取消订阅:" + b);
}
}
结果
11:43:27.537 5972-6020/com.wjn.rxdemo D/TAG: 当前线程:Thread-3
//5秒后 27+5=32
11:43:32.582 5972-5972/com.wjn.rxdemo D/TAG: 被观察者执行线程:main
11:43:32.582 5972-5972/com.wjn.rxdemo D/TAG: 是否取消订阅:false
11:43:32.582 5972-5972/com.wjn.rxdemo D/TAG: 线程切换后取消订阅关系
D/TAG: 关闭页面时是否取消订阅:true