前言

  • Rxjava,由于其基于事件流的链式调用、逻辑简洁 & 使用简单的特点,深受各大 Android开发者的欢迎。

如果还不了解RxJava,请看文章:Android:这是一篇 清晰 & 易懂的Rxjava 入门教程

  • RxJava如此受欢迎的原因,在于其提供了丰富 & 功能强大的操作符,几乎能完成所有的功能需求
  • 今天,我将为大家带来 Rxjava创建操作符的实际开发需求场景:网络请求嵌套回调 需求 ,并结合RetrofitRxJava 实现,希望大家会喜欢。
  1. 本系列文章主要基于 Rxjava 2.0
  2. 接下来的时间,我将持续推出 AndroidRxjava 2.0 的一系列文章,包括原理、操作符、应用场景、背压等等 ,有兴趣可以继续关注Carson_Ho的安卓开发笔记!!


目录


1. 需求场景

1.1 背景

需要进行嵌套网络请求:即在第1个网络请求成功后,继续再进行一次网络请求

如 先进行 用户注册 的网络请求, 待注册成功后回再继续发送 用户登录 的网络请求

1.2 冲突

嵌套实现网络请求较为复杂,即嵌套调用函数

下面展示的是结合 RetrofitRxJava的基本用法,即未用操作符前

// 发送注册网络请求的函数方法    private void register() {        api.register(new RegisterRequest())                .subscribeOn(Schedulers.io())               //在IO线程进行网络请求                .observeOn(AndroidSchedulers.mainThread())  //回到主线程去处理请求结果                .subscribe(new Consumer() {                    @Override                    public void accept(RegisterResponse registerResponse) throws Exception {                        Toast.makeText(MainActivity.this, "注册成功", Toast.LENGTH_SHORT).show();                        login();   //注册成功, 调用登录的方法                    }                }, new Consumer() {                    @Override                    public void accept(Throwable throwable) throws Exception {                        Toast.makeText(MainActivity.this, "注册失败", Toast.LENGTH_SHORT).show();                    }                });    }// 发送登录网络请求的函数方法private void login() {        api.login(new LoginRequest())                .subscribeOn(Schedulers.io())               //在IO线程进行网络请求                .observeOn(AndroidSchedulers.mainThread())  //回到主线程去处理请求结果                .subscribe(new Consumer() {                    @Override                    public void accept(LoginResponse loginResponse) throws Exception {                        Toast.makeText(MainActivity.this, "登录成功", Toast.LENGTH_SHORT).show();                    }                }, new Consumer() {                    @Override                    public void accept(Throwable throwable) throws Exception {                        Toast.makeText(MainActivity.this, "登录失败", Toast.LENGTH_SHORT).show();                    }                });    }

1.3 解决方案

结合 RxJava2中的变换操作符FlatMap()实现嵌套网络请求

关于该操作符的使用具体请看文章:Android RxJava:图文详解 变换操作符


2. 功能说明

  • 实现功能:发送嵌套网络请求(将英文翻译成中文,翻译两次)
  1. 为了让大家都能完成Demo,所以通过 公共的金山词霸API 来模拟 “注册 - 登录”嵌套网络请求
  2. 即先翻译 Register(注册),再翻译 Login(登录)
  • 实现方案:采用Get方法对 金山词霸API 发送网络请求

采用 Gson 进行数据解析


3. 具体实现

下面我将结合 RetrofitRxJava 实现网络请求嵌套

3.1 步骤说明

  1. 添加依赖
  2. 创建 接收服务器返回数据 的类
  3. 创建 用于描述网络请求 的接口(区别于Retrofit传统形式)
  4. 创建 Retrofit 实例
  5. 创建 网络请求接口实例 并 配置网络请求参数(区别于Retrofit传统形式)
  6. 发送网络请求(区别于Retrofit传统形式)
  7. 发送网络请求
  8. 对返回的数据进行处理

本实例侧重于说明 RxJava 的线程控制,关于Retrofit的使用请看文章:这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)

3.2 步骤实现

步骤1: 添加依赖

a. 在 Gradle加入Retrofit库的依赖

build.gradle

dependencies {// Android 支持 Rxjava// 此处一定要注意使用RxJava2的版本compile 'io.reactivex.rxjava2:rxjava:2.0.1'compile 'io.reactivex.rxjava2:rxandroid:2.0.1'// Android 支持 Retrofitcompile 'com.squareup.retrofit2:retrofit:2.1.0'// 衔接 Retrofit & RxJava// 此处一定要注意使用RxJava2的版本compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'// 支持Gson解析compile 'com.squareup.retrofit2:converter-gson:2.1.0'}

b. 添加 网络权限
AndroidManifest.xml

步骤2:创建 接收服务器返回数据 的类
  • 金山词霸API 的数据格式说明如下:
// URL模板http://fy.iciba.com/ajax.php// URL实例http://fy.iciba.com/ajax.php?a=fy&f=auto&t=auto&w=hello%20world// 参数说明:// a:固定值 fy// f:原文内容类型,日语取 ja,中文取 zh,英语取 en,韩语取 ko,德语取 de,西班牙语取 es,法语取 fr,自动则取 auto// t:译文内容类型,日语取 ja,中文取 zh,英语取 en,韩语取 ko,德语取 de,西班牙语取 es,法语取 fr,自动则取 auto// w:查询内容
  • 示例

  • 根据 金山词霸API 的数据格式,创建 接收服务器返回数据 的类:

为了演示是2个网络请求,所以对应设置2个接收服务器的数据类

<-- Translation1.java -->public class Translation1 {    private int status;    private content content;    private static class content {        private String from;        private String to;        private String vendor;        private String out;        private int errNo;    }    //定义 输出返回数据 的方法    public void show() {        Log.d("RxJava", "翻译内容 = " + content.out);    }}<-- Translation2.java -->public class Translation2 {    private int status;    private content content;    private static class content {        private String from;        private String to;        private String vendor;        private String out;        private int errNo;    }    //定义 输出返回数据 的方法    public void show() {        Log.d("RxJava", "翻译内容 = " + content.out);    }}
步骤3:创建 用于描述网络请求 的接口

采用 注解 + Observable<...>接口描述 网络请求参数

GetRequest_Interface.java

public interface GetRequest_Interface {    // 网络请求1    @GET("ajax.php?a=fy&f=auto&t=auto&w=hi%20register")    Observable getCall();    // 网络请求2    @GET("ajax.php?a=fy&f=auto&t=auto&w=hi%20login")    Observable getCall_2();    // 注解里传入 网络请求 的部分URL地址    // Retrofit把网络请求的URL分成了两部分:一部分放在Retrofit对象里,另一部分放在网络请求接口里    // 如果接口里的url是一个完整的网址,那么放在Retrofit对象里的URL可以忽略    // 采用Observable<...>接口    // getCall()是接受网络请求数据的方法}
接下来的步骤均在MainActivity.java内实现(请看注释)

MainActivity.java

public class MainActivity extends AppCompatActivity {        private static final String TAG = "Rxjava";        // 定义Observable接口类型的网络请求对象        Observable observable1;        Observable observable2;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            // 步骤1:创建Retrofit对象            Retrofit retrofit = new Retrofit.Builder()                    .baseUrl("http://fy.iciba.com/") // 设置 网络请求 Url                    .addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析(记得加入依赖)                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava                    .build();            // 步骤2:创建 网络请求接口 的实例            GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);            // 步骤3:采用Observable<...>形式 对 2个网络请求 进行封装            observable1 = request.getCall();            observable2 = request.getCall_2();            observable1.subscribeOn(Schedulers.io())               // (初始被观察者)切换到IO线程进行网络请求1                       .observeOn(AndroidSchedulers.mainThread())  // (新观察者)切换到主线程 处理网络请求1的结果                       .doOnNext(new Consumer() {                        @Override                        public void accept(Translation1 result) throws Exception {                            Log.d(TAG, "第1次网络请求成功");                            result.show();                            // 对第1次网络请求返回的结果进行操作 = 显示翻译结果                        }                    })                    .observeOn(Schedulers.io())                 // (新被观察者,同时也是新观察者)切换到IO线程去发起登录请求                                                                // 特别注意:因为flatMap是对初始被观察者作变换,所以对于旧被观察者,它是新观察者,所以通过observeOn切换线程                                                                // 但对于初始观察者,它则是新的被观察者                    .flatMap(new Function>() { // 作变换,即作嵌套网络请求                        @Override                        public ObservableSource apply(Translation1 result) throws Exception {                            // 将网络请求1转换成网络请求2,即发送网络请求2                            return observable2;                        }                    })                    .observeOn(AndroidSchedulers.mainThread())  // (初始观察者)切换到主线程 处理网络请求2的结果                    .subscribe(new Consumer() {                        @Override                        public void accept(Translation2 result) throws Exception {                            Log.d(TAG, "第2次网络请求成功");                            result.show();                            // 对第2次网络请求返回的结果进行操作 = 显示翻译结果                        }                    }, new Consumer() {                        @Override                        public void accept(Throwable throwable) throws Exception {                            System.out.println("登录失败");                        }                    });    }}

3.3 测试结果


4. Demo地址

Carson_Ho的Github地址 = RxJava2实战系列:网络请求嵌套回调

喜欢的麻烦点个star


5. 总结

  • 本文主要讲解了 Rxjava 变换操作符的实际开发需求场景:嵌套回调需求 ,并结合RetrofitRxJava 实现
  • 接下来的时间,我将持续推出 AndroidRxjava 2.0 的一系列文章,包括原理、操作符、应用场景、背压等等

  • 感兴趣的同学可以继续关注carson_ho的微信公众号


请帮顶 / 评论点赞!因为你的鼓励是我写作的最大动力!

更多相关文章

  1. Android(安卓)- 小功能 使用ImageView加载本地SdCard图片和加载
  2. Android轻松搭建MVVM + Retrofit + RxJava 及嵌入Android(安卓)A
  3. android sdk manager’s error’s solves
  4. Android(安卓)网络管理类的使用(一)
  5. Android获取网络状态
  6. 自定义HttpURLConnection工具类
  7. Android(安卓)Studio中http请求方式
  8. android(判断是否联网)
  9. Android客户端修改网页

随机推荐

  1. Android数字签名
  2. Android面试题集锦之Service
  3. 如何画Q版角色?绘画q版动漫人物
  4. Ubuntu系统-FFmpeg安装及环境配置
  5. iOS UITextView 实现类似微博的话题、提
  6. php生成WAP页面
  7. 手绘插画如何练习?学手绘插画步骤
  8. html制作课程表格代码(用HTML5标签设计课
  9. 还不会画嘴巴?零基础学动漫人物嘴巴
  10. 框架中用到的类和基本文件及App类,Router