RxJava线程控制
默认情况下被观察者和观察者是工作在同一个线程的,
我们可以通过一个Rxjava最基本的应用得到验证:
Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
Log.d("===", "被观察者线程 : " + Thread.currentThread().getName());
Log.d("===", "emit 1");
emitter.onNext(1);
}
});
Consumer<Integer> consumer = new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("===", "观察者线程 :" + Thread.currentThread().getName());
Log.d("===", "onNext: " + integer);
}
};
observable.subscribe(consumer);
这段代码只是在被观察者和观察者中分别打印出了自己工作的线程名称,然后我们得到的结果如下:
10-13 03:51:02.519 7920-7920/? D/===: 被观察者线程 : main
10-13 03:51:02.519 7920-7920/? D/===: emit 1
10-13 03:51:02.519 7920-7920/? D/===: 观察者线程 :main
10-13 03:51:02.519 7920-7920/? D/===: onNext: 1
可以看到在没有主动的进行线程控制的情况下,被观察者和观察者默认都是工作在同一个线程中,
因为我们这里是在Activity的onCreate方法中进行的,所以打印出来的都是在main线程中。
下面我们对上面的代码做一些修改:
observable.subscribeOn(Schedulers.newThread())
.subscribe(consumer);
打印结果:
10-13 03:52:56.446 9607-9647/vico.xin.mvpdemo D/===: 被观察者线程 : RxNewThreadScheduler-1
10-13 03:52:56.446 9607-9647/vico.xin.mvpdemo D/===: emit 1
10-13 03:52:56.446 9607-9647/vico.xin.mvpdemo D/===: 观察者线程 :RxNewThreadScheduler-1
10-13 03:52:56.446 9607-9647/vico.xin.mvpdemo D/===: onNext: 1
修改被观察者线程,观察者的线程也变了
再把代码修改一下:
observable.observeOn(Schedulers.newThread())
.subscribe(consumer);
打印结果:
10-13 03:55:44.360 12067-12067/vico.xin.mvpdemo D/===: 被观察者线程 : main
10-13 03:55:44.360 12067-12067/vico.xin.mvpdemo D/===: emit 1
10-13 03:55:44.363 12067-12104/vico.xin.mvpdemo D/===: 观察者线程 :RxNewThreadScheduler-1
10-13 03:55:44.363 12067-12104/vico.xin.mvpdemo D/===: onNext: 1
修改观察者的线程,被观察者并没有改变,还是在默认的main线程
所以到这里大致可以认为subscribeOn()是指定被观察者的线程,observeOn()是指定观察者线程的。
那么如果我想多次的更换被观察者和观察者的线程是不是可以呢? 还是把之前的代码做一些修改,如下:
observable.subscribeOn(Schedulers.newThread())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("===", "观察者线程 :" + Thread.currentThread().getName());
}
})
.observeOn(Schedulers.io())
.doOnNext(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("===", "观察者线程 :" + Thread.currentThread().getName());
}
})
.subscribe(consumer);
打印结果:
10-13 06:17:57.650 7859-7899/vico.xin.mvpdemo D/===: 被观察者线程 : RxNewThreadScheduler-1
10-13 06:17:57.654 7859-7899/vico.xin.mvpdemo D/===: emit 1
10-13 06:17:57.668 7859-7859/vico.xin.mvpdemo D/===: 观察者线程 :main
10-13 06:17:57.669 7859-7903/vico.xin.mvpdemo D/===: 观察者线程 :RxCachedThreadScheduler-2
10-13 06:17:57.669 7859-7903/vico.xin.mvpdemo D/===: 观察者线程 :RxCachedThreadScheduler-2
10-13 06:17:57.670 7859-7903/vico.xin.mvpdemo D/===: onNext: 1
我们具体分析一下打印结果,先说被观察者,如果我们不修改线程它应该默认的是在main线程中,我们调用了两次subscribeOn(),分别把线程改为一个新线程和IO线程,但是我们在打印结果中只看到了RxNewThreadScheduler-1 这个新线程,后面的IO线程并没有生效,
于是我们得出结论,被观察者虽然说可以多次的调用subscribeOn()修改线程,但是只有第一次会生效,后面的会被忽略掉。
再来看观察者,同样它默认工作在main线程中,然后调用了observeOn()两次去修改线程,
打印结果也显示修改了两次,这样就得出每调用observeOn()一次,观察者线程就修改一次。
线程控制在Android中的应用
应该说所有耗时的操作都可以利用Rxjava将线程调到非UI线程中去实现,然后得到结果后再到UI线程中来展示,例如网络请求,数据库操作等
最主要也是最常见的就是和Retrofit配合,来举一个简单的例子,模仿一个登录功能
首先要保证项目中已经引入了Retrofit,然后定义API接口:
public interface Api {
@FormUrlEncoded
@POST("user/login")
Observable<BaseDto<UserDto>> Login(@Field("json") String json);
}
//再创建一个Retrofit:
private static Retrofit create() {
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
return new Retrofit.Builder().baseUrl("your baseUrl")
.client(builder.build()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
//开始登录:
Api api = retrofit.create(Api.class);
api.login(request)
.subscribeOn(Schedulers.io()) 在IO线程进行网络请求 .observeOn(AndroidSchedulers.mainThread()) 回到主线程去处理请求结果
.subscribe(new Observer<UserDto>() {
@Override
public void onSubscribe(Disposable d) {}
@Override
public void onNext(UserDto userDto) {
Log.e("===","登录成功")
}
@Override
public void onError(Throwable e) {
Log.e("===","登录失败")
}
@Override
public void onComplete() {
}
});
结合前一章,应该在onSubscribe()中将Disposable 利用 CompositeDisposable.add()添加到CompositeDisposable容器中去,
然后在activity退出的时候调用CompositeDisposable.clear()解除订阅关系。
这就是一个最简单的Rxjava和Retrofit的组合使用。