准备工作
导入相关的依赖库,不要忘记导入 RxAndroid 的库
// 开头的两个是两个适配器的依赖,根据自己的需求加,官网还有更多适配器的选择
implementation 'com.squareup.retrofit2:converter-scalars:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.3'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
使用场景分析
在平时的安卓开发中,我们遇到像注册和登录这两个网络请求的时候,有时候会有这样的需求,我注册完了就紧接着要登录,通常遇到这钟情况的时候,我们都会选择在注册请求的回调当中接着去登录,这样子感觉还可以接受,只会有一层的嵌套,但是如果连续的请求更多的时候,就会在写代码的时候发现嵌套的层次太多了,代码的逻辑不容易读懂。
这个时候如果我们使用的是 Rxjava 的时候,就会发现一连串的逻辑从头写到尾,思路十分的清楚,代码也很好读,当然 Rxjava 本身还是需要大家花一定得时间去学习,在这里我推荐一个大神的教程,看他的教程再搭配自己的使用的话就会很有收获,大神博客,他把 Observable 和 Observer 比喻为水管,形容的很贴切,对没有学过 Rxjava1 的人也很友好。
先上代码
public interface LoginInterface {
@GET("***")
Call login(@Query("StudentID") String studentId, @Query("Password") String password, @Query("**") String param1, @Query("**") String param2);
@GET("***")
Observable getUserInfo(@Query("StudentID") String studentId, @Query("**") String param1, @Query("**") String param2);
}
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
// 换成你自己的URL
.baseUrl("********************")
.build();
LoginInterface mLoginInterface = retrofit.create(LoginInterface.class);
上面的这些代码和我们直接使用 Retrofit 来进行网络请求没有任何区别,但是 Retrofit 可以和 Rxjava 搭配进行网络请求,当然这里还忘了介绍 Rxjava 的另一个优点,就是线程切换十分方便,可以在下面的代码里面体现出来,让我们接着看下面的代码。
mLoginInterface
.login_1(studentId, password, String.valueOf(currentTime), md5Str.substring(3, 18).toUpperCase())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(new Consumer() {
@Override
public void accept(LoginBean loginBean) throws Exception {
if (loginBean.getCode() != 1) {
AlertDialog builder = new AlertDialog.Builder(LoginActivity.this)
.setMessage(loginBean.getMsg())
.setTitle("提示!")
.setPositiveButton("我知道了", null)
.create();
builder.show();
dialog.cancel();
loginButton.setClickable(true);
}
Log.d(TAG, "登录成功!");
Log.d(TAG, "" + loginBean.getCode());
}
})
.doOnError(new Consumer() {
@Override
public void accept(Throwable throwable) throws Exception {
loginButton.setClickable(true);
Log.d(TAG, "调用失败");
}
})
.observeOn(Schedulers.io())
.flatMap(new Function>() {
@Override
public Observable apply(LoginBean loginBean) throws Exception {
if (loginBean.getCode() != 1) {
mDisposable.dispose();
}
long currentTime = System.currentTimeMillis();
String md5Str = Md5Util.md5(KEY + currentTime);
return mLoginInterface.getUserInfo(studentId, String.valueOf(currentTime), md5Str.substring(3, 18).toUpperCase());
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
mDisposable = d;
}
@Override
public void onNext(WeixinConnectBean response) {
getCourseData(studentId, password);
progressAnimator.start();
loginButton.setClickable(true);
String userName = response.getStuName();
String major = response.getMajor();
SharePreferenceLab.getInstance().setUsername(LoginActivity.this, userName);
SharePreferenceLab.getInstance().setMajor(LoginActivity.this, major);
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "调用失败");
Toast.makeText(LoginActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
dialog.cancel();
loginButton.setClickable(true);
}
@Override
public void onComplete() {
}
});
大家可能第一反应会觉得代码不是很简洁,甚至有点不好理解,但是但凡大家对 Rxjava 有一定的掌握,都会觉得这样写很容易理解,特别是链接的请求更加多的时候,优势越发明显。
链式请求的难点
我觉得链式请求最需要注意的两个点一个是操作符的使用,另一个就是中断请求。我们接下来来分析这两个点。
FlatMap 操作符的使用
在这种情况下我们选择使用 Rxjava 的 FlatMap 操作符,这样子我们就可以将上一个请求返回的结果转换成下一个请求,这样就可以接着进行下一个请求了,根据上面的例子,我们需要实现一个 FunctionmLoginInterface.getUserInfo(studentId, String.valueOf(currentTime), md5Str.substring(3, 18).toUpperCase())
,当然这里还要注意一点,之前我们切换了线程到了主线程,这里我们需要回到 io 线程进行网络请求,但是这里还是用的是 observeOn 来切换线程。
中断请求
这里我们就要用 Rxjava 里面的一个新的东西叫作 Disposable,我们通过它来中止请求,这一点在我之前那个大神介绍的文章里面介绍的很仔细,他在里面比喻说相当于切断了上下游的联系,但是我们在哪里获取的 Disposable 的呢,大家看最后面的代码会发现,我们在订阅的时候,会先调用 onSubscribe 这个方法,这个方法的参数里面会给我们一个 Disposable 的引用,我们持着这个引用在需要中断的时候调用 dispose 方法,就会中止请求。
总结
当然 Rxjava 的操作符远不止这么一些,在以后还是会结合使用场景来进行分析,相信使用多了就会了解 Rxjava 的便利性。