Rxjava学习(二)
关于Rxjava的线程控制
正常情况下,上游和下游是工作在同一个线程中的,也就是说:上游在哪个线程中发送事件,下游就在哪个线程中接收事件
在Android中,一个Activity的所有默认动作都是在主线程中进行的:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, Thread.currentThread().getName());
}
//结果
03-14 08:03:04.779 5051-5051/com.example.uds.recyclerviewtest D/MAP: main
在RxJava中:
当我们在主线程中创建一个上游 Observable 来发送事件,则这个上游就默认在主线程中发送事件
当我们在主线程中去创建一个下游 Observer 来接收事件,则这个下游默认就在主线程中接收事件
Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
Log.d(TAG, Thread.currentThread().getName());
}
});
Consumer<Integer> consumer = new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG,Thread.currentThread().getName());
}
};
observable.subscribe(consumer);
//结果
03-14 08:03:04.779 5051-5051/com.example.uds.recyclerviewtest D/MAP: main
03-14 08:09:21.643 10661-10661/com.example.uds.recyclerviewtest D/MAP: main
我们的正常需求是在子线程中作耗时操作,然后回到主线程中来更新UI
所以就要求上游是在子线程中进行发送事件,下游是在主线程中接收事件的
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
Log.d(TAG,Thread.currentThread().getName());
e.onNext(1);
}
}).subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG,integer + " onNext");
Log.d(TAG,Thread.currentThread().getName());
}
});
//结果
03-14 08:17:29.620 17840-17913/com.example.uds.recyclerviewtest D/MAP: RxNewThreadScheduler-1
03-14 08:17:29.798 17840-17840/com.example.uds.recyclerviewtest D/MAP: 1 onNext
03-14 08:17:29.798 17840-17840/com.example.uds.recyclerviewtest D/MAP: main
subscribeOn(Schedules.newThread()) 方法表示上游事件发生的线程位置,新建了一个线程
observeOn(AndroidSchedulers.mainThread()) 方法表示观察者即下游事件发生的线程位置,在主线程中
当我们把上述内容放到线程中,observeOn(AndroidSchedulers.mainThread()) 依然是表示在主线程中
new Thread(new Runnable() {
@Override
public void run() {
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
Log.d(TAG,Thread.currentThread().getName());
e.onNext(1);
}
}).subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG,integer + " onNext");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
textView.setText("2");//布局文件定义了一个TextView
Log.d(TAG,Thread.currentThread().getName());
}
});
}
}).start();
指定线程的特点
subscribeOn() :指定上游发送事件的线程
多次指定上游的线程只有第一次指定的有效,也就是说多次调用subscribeOn() 只有第一次的有效,其余的会被忽略
observeOn() :指定下游接收事件的线程
多次指定下游的线程是可以的,但是每次调用一次 observeOn() ,下游的线程就会切换一次
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
Log.d(TAG,Thread.currentThread().getName());
e.onNext(1);
}
}).subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG,"After observeOn Main");
}
})
.observeOn(Schedulers.io())
.doOnNext(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG,"After observeOn io");
}
})
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG,integer + " onNext");
Log.d(TAG,Thread.currentThread().getName());
}
});
//结果
03-14 13:52:27.900 7134-7200/com.example.uds.recyclerviewtest D/MAP: RxNewThreadScheduler-1
03-14 13:52:28.064 7134-7134/com.example.uds.recyclerviewtest D/MAP: After observeOn Main
03-14 13:52:28.077 7134-7206/com.example.uds.recyclerviewtest D/MAP: After observeOn io
03-14 13:52:28.077 7134-7206/com.example.uds.recyclerviewtest D/MAP: 1 onNext
03-14 13:52:28.077 7134-7206/com.example.uds.recyclerviewtest D/MAP: RxCachedThreadScheduler-1
RxJavaz中内置的线程
- Schedulers.io() 代表io操作的线程,通常用于网络,读写文件等io密集型的操作
- Schedulers.computation() 代表CPU计算密集型的操作,例如需要大量计算的操作
- Schedulers.newThread() 代表一个常规的新线程
- AndroidSchedulers.mainThread() 代表Android的主线程
这些类型的线程在Rxjava中使用了线程池来进行了维护,所以效率较高我们可以直接使用
网络请求
如下的例子是在上游进行网络请求,然后在下游更新UI,会存在如下问题,当我们网络请求完毕去更新UI的时候,Activity退出了就会出现APP崩溃的问题
public interface API{
@POST
@FormUrlEncoded
Observable<Response> login(@Field("username") String username ,@Field("password") String password)
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("xxxx")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory)
.build();
API api = retrofit.create(API.class);
api.login("admin","admin")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Response>(){
@Override
public void onSubscribe(Disposable d) {}
@Override
public void onNext(LoginResponse value) {}
@Override
public void onError(Throwable e) {
Toast.makeText(mContext, "登录失败", Toast.LENGTH_SHORT).show();
}
@Override
public void onComplete() {
Toast.makeText(mContext, "登录成功", Toast.LENGTH_SHORT).show();
}
});
这里我们就需要将 Disposable 对象进行保存 ,在退出activity的时候将管道切断