RxJava 与 Retrofit 搭配的链式调用

准备工作

导入相关的依赖库,不要忘记导入 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 操作符,这样子我们就可以将上一个请求返回的结果转换成下一个请求,这样就可以接着进行下一个请求了,根据上面的例子,我们需要实现一个 Function>() 这个类里的 apply 这个方法,最后返回的一个 Observable,也就是另一个请求,在这里我们返回的是 mLoginInterface.getUserInfo(studentId, String.valueOf(currentTime), md5Str.substring(3, 18).toUpperCase()) ,当然这里还要注意一点,之前我们切换了线程到了主线程,这里我们需要回到 io 线程进行网络请求,但是这里还是用的是 observeOn 来切换线程。

中断请求

这里我们就要用 Rxjava 里面的一个新的东西叫作 Disposable,我们通过它来中止请求,这一点在我之前那个大神介绍的文章里面介绍的很仔细,他在里面比喻说相当于切断了上下游的联系,但是我们在哪里获取的 Disposable 的呢,大家看最后面的代码会发现,我们在订阅的时候,会先调用 onSubscribe 这个方法,这个方法的参数里面会给我们一个 Disposable 的引用,我们持着这个引用在需要中断的时候调用 dispose 方法,就会中止请求。

总结

当然 Rxjava 的操作符远不止这么一些,在以后还是会结合使用场景来进行分析,相信使用多了就会了解 Rxjava 的便利性。

你可能感兴趣的:(RxJava 与 Retrofit 搭配的链式调用)