Android RxJava 实战系列:优雅实现 网络请求嵌套回调

原创 2017年10月23日 09:47:46

前言

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

Github截图

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


  • RxJava如此受欢迎的原因,在于其提供了丰富 & 功能强大的操作符,几乎能完成所有的功能需求
  • 今天,我将为大家带来 Rxjava创建操作符的实际开发需求场景:网络请求嵌套回调 需求 ,并结合RetrofitRxJava 实现,希望大家会喜欢。

  1. 本系列文章主要基于 Rxjava 2.0
  2. 接下来的时间,我将持续推出 AndroidRxjava 2.0 的一系列文章,包括原理、操作符、应用场景、背压等等 ,有兴趣可以继续关注Carson_Ho的安卓开发笔记!!

  3. 示意图

目录

示意图


1. 需求场景

1.1 背景

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

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

1.2 冲突

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

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

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

<uses-permission android:name="android.permission.INTERNET"/>
步骤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格式说明

  • 根据 金山词霸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<Translation1> getCall();

    // 网络请求2
    @GET("ajax.php?a=fy&f=auto&t=auto&w=hi%20login")
    Observable<Translation2> 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<Translation1> observable1;
        Observable<Translation2> 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<Translation1>() {
                        @Override
                        public void accept(Translation1 result) throws Exception {
                            Log.d(TAG, "第1次网络请求成功");
                            result.show();
                            // 对第1次网络请求返回的结果进行操作 = 显示翻译结果
                        }
                    })

                    .observeOn(Schedulers.io())                 // (新被观察者,同时也是新观察者)切换到IO线程去发起登录请求
                                                                // 特别注意:因为flatMap是对初始被观察者作变换,所以对于旧被观察者,它是新观察者,所以通过observeOn切换线程
                                                                // 但对于初始观察者,它则是新的被观察者
                    .flatMap(new Function<Translation1, ObservableSource<Translation2>>() { // 作变换,即作嵌套网络请求
                        @Override
                        public ObservableSource<Translation2> apply(Translation1 result) throws Exception {
                            // 将网络请求1转换成网络请求2,即发送网络请求2
                            return observable2;
                        }
                    })

                    .observeOn(AndroidSchedulers.mainThread())  // (初始观察者)切换到主线程 处理网络请求2的结果
                    .subscribe(new Consumer<Translation2>() {
                        @Override
                        public void accept(Translation2 result) throws Exception {
                            Log.d(TAG, "第2次网络请求成功");
                            result.show();
                            // 对第2次网络请求返回的结果进行操作 = 显示翻译结果
                        }
                    }, new Consumer<Throwable>() {
                        @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的安卓开发笔记!!

示意图


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

版权声明:本文为博主原创文章,未经博主允许不得转载,更多文章请继续关注Carson_Ho的博客!

RxJava处理嵌套请求

互联网应用开发中由于请求网络数据频繁,往往后面一个请求的参数是前面一个请求的结果,于是经常需要在前面一个请求的响应中去发送第二个请求,从而造成“请求嵌套”的问题。如果层次比较多,代码可读性和效率都是问...
  • binyao02123202
  • binyao02123202
  • 2017年06月27日 16:37
  • 619

Rxjava2.x 使用强大的操作符来处理嵌套请求

版权声明:本文为博主原创文章,转载请声明出处哦,谢谢。最近遇到一个需求,大概内容如下:1、请求A接口返回对象集合(假设对象是VideoTest 有一个参数url跟参数名id); 2、需要再根据每个对...
  • Dreamfree3
  • Dreamfree3
  • 2017年09月07日 16:48
  • 949

android http多请求异步封装对你绝对有用

本demo主要对异步请求封装  可用作基本项目框架来使用 网络请求等等小细节已经ok 如有需要请进一步更改 1)封装HttpClient 2)由于用到线程池,可以进行多任务网络请求操作 3)没有网络的...
  • vpingchangxin
  • vpingchangxin
  • 2014年04月10日 19:34
  • 34827

RxJava系列第一弹——RxJava入门篇

概述:RxJava系列文章第一篇 RxJava入门篇 介绍RxJava是什么和基本使用。一 RxJava是什么1 来自官网的介绍a library for composing asynchronous...
  • qq_33553515
  • qq_33553515
  • 2017年03月17日 20:24
  • 746

一个很详细的RxJava讲解,一看就懂

这是转载的第二篇RxJava的文章了,感觉比之前的那篇写得好,更易懂且更全面。 当然学习框架不在于看几篇文章,而在于做多少练习,然而看到还是觉得值得一转。...
  • u014137988
  • u014137988
  • 2016年12月09日 14:26
  • 1489

Retrofit+Rxjava实现嵌套逻辑的链式调用

最近做app有一个需求,service的某个接口(B接口)调用很慢,所以不能频繁的调用,然后service就想了一个逻辑:先返回一个调用速度快的接口(A接口),里面有一个字段,一旦这个字段发生了改变,...
  • robin_java
  • robin_java
  • 2016年11月28日 11:04
  • 2685

rxjava嵌套访问

在学习rxjava的过程中,有遇到过关于rxjava嵌套请求
  • u011557841
  • u011557841
  • 2017年03月09日 15:49
  • 1096

RxJava使用场景小结

取数据先检查缓存的场景取数据,首先检查内存是否有缓存 然后检查文件缓存中是否有 最后才从网络中取 前面任何一个条件满足,就不会执行后面的final Observable memory = ...
  • lzyzsd
  • lzyzsd
  • 2015年11月30日 23:16
  • 44356

Android开发学习之路--RxAndroid之初体验

学了一段时间android,看了部分的项目代码,然后想想老是学基础也够枯燥乏味的,那么就来学习学习新东西吧,相信很多学java的都听说过RxJava,那么android下也有RxAndroid。   ...
  • eastmoon502136
  • eastmoon502136
  • 2016年03月11日 21:53
  • 53504

RxJava(RxAndroid)基本使用入门

介绍RxJava(RxAndroid)基础入门知识,帮助入门上手RxJava(RxAndroid)库。
  • chen_zhang_yu
  • chen_zhang_yu
  • 2016年10月23日 13:45
  • 13418
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android RxJava 实战系列:优雅实现 网络请求嵌套回调
举报原因:
原因补充:

(最多只允许输入30个字)