一.场景

在普通操作的代码中,如果我们想要实现登录功能,那么势必要请求后台服务,获取登录的结果,然后根据结果做不同的更新​​UI​​的操作。由于主线程不能执行耗时操作,所以网络请求正常情况下都要放在子线程执行,然后需要借助​​Handler​​将在子线程获得的结果返回到主线程中,并更新​​UI​​。​​RxJava​​之所以强大,我们在使用他进行线程切换时,不需要自己去创建​​Handler​​,只需要一句代码就能完成线程切换,这是为什么要进行线程切换的原因。

二.切换类型

我们先通过一个例子学习在RxJava中如何切换线程。

Observable observable = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
e.onNext(1);
Log.d(TAG, "subscribe: "+Thread.currentThread().getName());
}
});

Observer observer = new Observer<Integer>() {
Disposable d;
@Override
public void onSubscribe(Disposable d) {
this.d=d;
}

@Override
public void onNext(Integer o) {
Log.d(TAG, "onNext: "+Thread.currentThread().getName());
}

@Override
public void onError(Throwable e) {

}

@Override
public void onComplete() {

}
};
observable.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);


log日志如图


写给小白的RxJava教程(二)_ide

其中用来指定线程的就是

observable.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);


2.1 Schedulers

  • ​Schedulers.newThread()​​:一个常规的子线程
  • ​AndroidSchedulers.mainThread()​​:Activity所在的主线程
  • ​Schedulers.io()​​:适合IO密集型的操作
  • ​Schedulers.computation()​​:适合计算密集型的操作

2.2 subscribeOn

用来指定被观察者所在的线程,一般来说,我们在被观察者的内部执行网络请求或者​​IO​​操作,所以放在子线程去执行。

注意一点,​​subscribeOn​​方法如果被调用多次,以第一次调用时指定的线程为准,看如下代码

observable.subscribeOn(Schedulers.computation())
.subscribeOn(Schedulers.io())
.subscribeOn(Schedulers.newThread())


这上面上次调用了​​subscribeOn​​方法,最后​​Observable​​会依照第一次调用时指定的线程运行。

2.3 observerOn

它用来指定观察者所在的线程,由于观察者接受了被观察者操作的结果,有可能需要更新​​UI​​,所以大部分情况下,我们都会将它指定在主线程之中。

同样需要注意一点,​​observerOn​​方法多次被调用时,以最后一次指定的线程为准,即调用一次​​observerOn​​方法,线程便会切换一次。

三.登录实例

下面我们实战一个登录场景,观察RxJava切换线程的详细操作。

步骤一:先定义一个接口,这个接口就是登录接口,接口内有一个登录方法,该登录方法返回一个Observable对象,并且通过retrofit的注解,添加用户名和密码。

import io.reactivex.Observable;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;

public interface LoginService {
//FormUrlEncoded表明这是一个表单请求
@FormUrlEncoded
@POST("login")
Observable<Result> userLogin(@Field("userAccount") String userAccount, @Field("userPwd") String userPwd);
}


步骤二:定义好接口,我们需要创建网络请求

private void userLogin(String userAccount,String userPwd){
String baseUrl = "http://10.138.51.142:8080/user/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
LoginService loginService = retrofit.create(LoginService.class);
loginService.userLogin(userAccount,userPwd)
.subscribeOn(Schedulers.io())//网络请求在子线程中执行
.observeOn(AndroidSchedulers.mainThread())//observer在主线程中执行,可以直接更新UI
.subscribe(new Observer<Result>() {
@Override
public void onSubscribe(Disposable d) {

}

@Override
public void onNext(Result result) {
Log.d(TAG, "onSubscribe: "+result.getMsg()+"---"+result.getRes()+"---"+result.getType());
if(result.getRes().equals("success")){
Toast.makeText(getApplicationContext(), "登录成功", Toast.LENGTH_SHORT).show();
}
}

@Override
public void onError(Throwable e) {
Log.d(TAG, "onSubscribe: "+e.getMessage());
}

@Override
public void onComplete() {
Log.d(TAG, "onSubscribe: ");
}
});
}


结果显示:

写给小白的RxJava教程(二)_java_02

四.总结

RxJava执行线程切换有多么方便,终于不用再自己写handler了,并且使用retrofit+RaJava使网络请求更加简单了!