海安零距离 海安论坛 海安新闻 海安

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2146|回复: 0

RxHttp 让你眼前一亮的Http请求框架

[复制链接]

6234

主题

6234

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
18718
发表于 2019-12-27 14:16 | 显示全部楼层 |阅读模式
1、前言

RxHttp在本年4月份一经推出,就受到了广大Android 开发者的喜好,停止本文发表在github上已有1100+star,为此,我本身也建个RxHttp&RxLife 的群(群号:378530627)如今群里也有将近180号人,里面有不少小同伴提了很多有价值的创意,才使得RxHttp一直坚持走到了如今,在此,感谢各人的喜好。
这期间,一直有人问我,retrofit不香吗?之前不知道该怎样答复这个标题,如今我想说,香!!retrofit无疑是如今综合得分最高的选手,但它也有它的不足。
RxHttp相较于retrofit,功能上,两者均能实现,并无多大差别,更多的差别体现功能的使用上,也就是易用性,如对文件上传/下载/进度监听的利用上,RxHttp用及简的API,可以说碾压retrofit;另外在baseUrl、公共参数/请求头、请求加解密等功能上的易用性都要优于retrofit;然而这些,个人以为都不算什么,个人以为RxHttp最大的上风在于它近乎为0的上手本钱、极简的API以及高扩展性,看完这篇文章,信任你会有同感。
那RxHttp就没有缺点吗?有,那就是它的稳定性如今还不如retrofit,毕竟RxHttp刚出道8个月,且全部是我一个人在维护,固然,并不是说RxHttp不稳定,RxHttp未开源前,在我司的项目已经使用了近2年,接着本年4月份将其开源,至今大巨微小已迭代20多个版本,如今用的人也不在少数,可以说很稳定了。
2、简介

RxHttp是基于OkHttp的二次封装,并与RxJava做到无缝衔接,一条链就能发送任意请求。告急上风如下:
1. 支持Gson、Xml、ProtoBuf、FastJson品级三方数据剖析工具
2. 支持Get、Post、Put、Delete等任意请求方式,可自定义请求方式
3. 支持在Activity/Fragment/View/ViewModel/任意类中,主动关闭请求
4. 支持同一加解密,且可对单个请求设置是否加解密
5. 支持添加公共参数/头部,且可对单个请求设置是否添加公共参数/头部
6. 史上最优雅的实现文件上传/下载及进度的监听,且支持断点下载
7. 史上最优雅的对错误同一处置处罚,且不冲破Lambda表达式
8. 史上最优雅的处置处罚多个BaseUrl及动态BaseUrl
9. 史上最优雅的处置处罚网络缓存
10. 30秒即可上手,学习本钱极低
gradle依赖
  1. implementation 'com.rxjava.rxhttp:rxhttp:1.3.6'//注解处置处罚器,天生RxHttp类,即可一条链发送请求annotationProcessor 'com.rxjava.rxhttp:rxhttp-compiler:1.3.6'//管理RxJava及生命周期,Activity/Fragment 烧毁,主动关闭未完成的请求implementation 'com.rxjava.rxlife:rxlife:1.1.0'//非必须 根据本身需求选择Converter  RxHttp默认内置了GsonConverterimplementation 'com.rxjava.rxhttp:converter-jackson:1.3.6'implementation 'com.rxjava.rxhttp:converter-fastjson:1.3.6'implementation 'com.rxjava.rxhttp:converter-protobuf:1.3.6'implementation 'com.rxjava.rxhttp:converter-simplexml:1.3.6'
复制代码
注:kotlin用户,请使用kapt替代annotationProcessor
缓存功能,请检察:RxHttp 全网Http缓存最优解
3、使用

3.1、预备工作

RxHttp 要求项目使用Java 8,请在 app 的 build.gradle 文件中添加以下代码
  1. compileOptions {    sourceCompatibility JavaVersion.VERSION_1_8    targetCompatibility JavaVersion.VERSION_1_8}
复制代码
此时,再Rebuild一下项目(通过Rebuild天生RxHttp类),就可以开始RxHttp的入坑之旅
3.2、配置默认的BaseUrl

通过@DefaultDomain注解配置默认域名,如下:
  1. public class Url {    @DefaultDomain //设置为默认域名    public static String baseUrl = "https://www.wanandroid.com/";}
复制代码
此步调好坏必须的,这里先介绍@DefaultDomain注解的用法,更多有关域名的介绍,请检察本文3.6章节----多域名/动态域名
3.3、请求三部曲

先来看看怎样发送一个最简单的请求,如下
  1. RxHttp.get("http://...")  //第一步, 通过get、postXxx、putXxx等方法,确定请求范例             .asString()           //第二步, 通过asXxx系列方法,确定返回数据范例        .subscribe(s -> {     //第三步, 订阅回调(此步调同RxJava订阅观察者)        //请求乐成                                             }, throwable -> {                                          //请求失败                                             });                                                
复制代码
是的,不消猜疑,就是这么简单,告急的变乱说3遍
任意请求,任意返回数据范例,皆遵照请求三部曲
任意请求,任意返回数据范例,皆遵照请求三部曲
任意请求,任意返回数据范例,皆遵照请求三部曲
到这,你已经把握了RxHttp的英华,我们只需牢记请求三部曲,使用RxHttp就会得心应手。
3.3.1、第一部曲:确定请求范例

RxHttp内部共提供了14个请求方法,如下:
  1. RxHttp.get(String)              //get请求    参数拼接在url反面RxHttp.head(String)             //head请求   参数拼接在url反面RxHttp.postForm(String)         //post请求   参数以{application/x-www-form-urlencoded}情势提交RxHttp.postJson(String)         //post请求   参数以{application/json; charset=utf-8}情势提交,发送Json对象RxHttp.postJsonArray(String)    //post请求   参数以{application/json; charset=utf-8}情势提交,发送Json数组RxHttp.putForm(String)          //put请求    参数以{application/x-www-form-urlencoded}情势提交RxHttp.putJson(String)          //put请求    参数以{application/json; charset=utf-8}情势提交,发送Json对象RxHttp.putJsonArray(String)     //put请求    参数以{application/json; charset=utf-8}情势提交,发送Json数组RxHttp.patchForm(String)        //patch请求  参数以{application/x-www-form-urlencoded}情势提交RxHttp.patchJson(String)        //patch请求  参数以{application/json; charset=utf-8}情势提交,发送Json对象RxHttp.patchJsonArray(String)   //patch请求  参数以{application/json; charset=utf-8}情势提交,发送Json数组RxHttp.deleteForm(String)       //delete请求 参数以{application/x-www-form-urlencoded}情势提交RxHttp.deleteJson(String)       //delete请求 参数以{application/json; charset=utf-8}情势提交,发送Json对象RxHttp.deleteJsonArray(String)  //delete请求 参数以{application/json; charset=utf-8}情势提交,发送Json数组
复制代码
以上14个请求方法你会发现,着实就6个范例,分别对应是Get、Head、Post、Put、Patch、Delete方法,只是此中Post、Put、Patch、Delete各有3个方法有差别情势的提交方式,只必要根据本身的需求选择就好。
如以上方法还不能满意你的需求,我们还可以通过@Param注解自定义请求方法,有关注解的使用,本文后续会详细介绍。
注:当调用xxxForm方法发送请求时,通过setMultiForm()方法或者调用addFile(String, File)添加文件时,内部会主动将参数以{multipart/form-data}方式提交
添加参数/请求头
确定请求方法后,我们就可以调用一系列addXxx()方法添加参数/请求头,如下:
  1. RxHttp.get("/service/...")       //发送get请求    .add("key", "value")         //添加参数    .addAll(new HashMap())     //通过Map添加多个参数    .addHeader("deviceType", "android")     //添加请求头    ...
复制代码
任意请求,都可调用以上3个方法添加参数/请求头,固然,在差别的请求方式下,也会有差别的addXxx方法供开发者调用。如下:
  1. //postJson请求方法下会有更多addAll等方法可供调用RxHttp.postJson("/service/...") //发送post Json请求    .addAll(new JsonObject())   //通过json对象添加多个参数    .addAll("{\"height\":180,\"weight\":70}") //通过json字符串添加多个参数    ...//postForm请求方法下会有一系列addFile方法可供调用RxHttp.postForm("/service/...")  //发送post表单请求    .addFile("file", new File("xxx/1.png")) //添加单个文件    .addFile("fileList", new ArrayList()) //添加多个文件    ...
复制代码
以上只列出了几个常用的addXxx方法,更多方法请下载源码体验。
3.3.2、第二部曲:确定返回数据范例

添加好参数/请求头后,正式进入第二部曲,确定返回数据范例,我们通过asXxx方法确定返回范例,好比,我们要返回一个Student对象,就可以通过asObject(Class)方法,如下:
  1. RxHttp.postForm("/service/...")  //发送post表单请求    .add("key", "value")         //添加参数,可调用多次    .asObject(Student.class)    //返回Student范例    .subscribe(student -> {           //请求乐成,这里就能拿到 Student对象                   }, throwable -> {                 //请求失败                    });   
复制代码
假如要返回Student对象列表,则可以通过asList(Class)方法,如下:
  1. RxHttp.postForm("/service/...")  //发送post表单请求    .add("key", "value")         //添加参数,可调用多次    .asList(Student.class)       //返回List范例    .subscribe(students -> {           //请求乐成,这里就能拿到 Student对象列表                   }, throwable -> {                 //请求失败                    });   
复制代码
剖析Response范例数据
然而,现实开发中,大多数人的接口,返回的数据布局都类似下面的这个样子
  1. public class Response {    private int    code;    private String msg;    private T      data;    //这里省略get、set方法}
复制代码
对于这种数据布局,按传统的写法,每次都要对code做判断,假如有100个请求,就要判断100次,真的会逼死欺压症患者。
RxHttp对于这种环境,给出完美的答案,好比Response里面的T代表一个Student对象,则可以通过asResponse(Class)方法获取,如下:
  1. RxHttp.postForm("/service/...")   //发送post表单请求    .add("key", "value")          //添加参数,可调用多次    .asResponse(Student.class)    //返回Student范例    .subscribe(student -> {           //请求乐成,这里能拿到 Student对象                   }, throwable -> {                 //请求失败                    });   
复制代码
假如Response里面的T代表一个List列表对象,则可以通过asResponseList(Class)方法获取,如下
  1. RxHttp.postForm("/service/...")   //发送post表单请求    .add("key", "value")          //添加参数,可调用多次    .asResponseList(Student.class)    //返回List范例    .subscribe(students -> {           //请求乐成,这里能拿到List列表对象                   }, throwable -> {                 //请求失败                    });   
复制代码
更多时间,我们的列表数据是分页的,类似下面的数据布局
  1. {    "code": 0,    "msg": "",    "data": {        "totalPage": 0,        "list": []    }}
复制代码
此时,调用RxHttp的asResponsePageList(Class)方法依然可以完美办理,如下:
  1. RxHttp.postForm("/service/...")   //发送post表单请求    .add("key", "value")          //添加参数,可调用多次    .asResponsePageList(Student.class)    //返回PageList范例    .subscribe(pageList -> {           //请求乐成,这里能拿到PageList列表对象        int totalPage = pageList.getTotalPage();   //总页数       List students = pageList.getData();  //单页列表数据            }, throwable -> {                 //请求失败                    });   
复制代码
到这,估计很多人会问我:

  • 你的code在那里判断的?
  • 我的code是100或者别的值才代表精确,怎么改?
  • 我的Response类里面的字段名,跟你的都不一样,怎么该?
  • 你这乐成的时间直接返回Response里面的T,那我还要拿到code做其他的判断,实行差别业务逻辑,怎么办?
这里可以先告诉各人,asResponse(Class)、asResponseList(Class)、asResponsePageList(Class)这3个方法并不是RxHttp内部提供的,而是通过自定义剖析器天生,里面的code判断、Response类都是开发者自定义的,怎样自定义剖析器,请检察本文5.1章节----自定义Parser。
接着答复第4个标题,怎样拿到code做其他的业务逻辑判断,很简单,我们只需用OnError接口处置处罚错误回调即可,如下:
  1. RxHttp.postForm("/service/...")   //发送post表单请求    .add("key", "value")          //添加参数,可调用多次    .asResponse(Student.class)    //返回Student范例    .subscribe(student -> {           //请求乐成,这里能拿到 Student对象                   }, (OnError) error -> {     //留意,这里要用OnError接口,此中error是一个ErrorInfo对象          //失败回调        //拿到code字段,此时就可以对code做判断,实行差别的业务逻辑         int code = error.getErrorCode();             String errorMsg = error.getErrorMsg()  //拿到msg字段                 });   
复制代码
注:上面的OnError接口并非是RxHttp内部提供的,而是自定义的,在Demo里可以找到
以上介绍的5个asXxx方法,可以说根本涵盖80%以上的业务场景,接下来我们看看RxHttp都提供了哪些asXxx方法,如下:

RxHttp内部共提供了23个asXXX方法,此中:

  • 有7个是返回根本范例的包装范例,如:asInteger、asBoolean、asLong等等;
  • 另有7个是返回对象范例,如:asString、asBitmap、asList、asMap(3个)以及最常用asObject方法;
  • 剩下9个是asParser(Parser)、 asUpload系列方法及asDownload系列方法。
duang、duang、duang !!! 划重点,这里我可以告诉各人,着试蛋面的14个方法,终极都是通过asParser(Parser)方法实现的,详细实现过程,这里先跳过,后续会详细解说。
3.3.3、第三部曲:订阅回调

这一步就很简单了,在第二部曲中,asXxx方法会返回Observable对象,没错,就是RxJava内部的Observable对象,此时我们便可通过subscribe系列方法订阅回调,如下:
  1. //不处置处罚任何回调RxHttp.postForm("/service/...")   //发送post表单请求    .add("key", "value")          //添加参数,可调用多次    .asResponseList(Student.class)    //返回List范例    .subscribe();    //不订阅任何回调    //仅订阅乐成回调RxHttp.postForm("/service/...")   //发送post表单请求    .add("key", "value")          //添加参数,可调用多次    .asResponseList(Student.class)    //返回List范例    .subscribe(students -> {           //请求乐成,这里能拿到List列表对象                   });        //订阅乐成与失败回调RxHttp.postForm("/service/...")   //发送post表单请求    .add("key", "value")          //添加参数,可调用多次    .asResponseList(Student.class)    //返回List范例    .subscribe(students -> {           //请求乐成,这里能拿到List列表对象                   }, throwable -> {                 //请求失败                    });    //等等,省略
复制代码
另外,我们还可以订阅请求开始/结束的回调,如下:
  1. RxHttp.get("/service/...")    .asString()    .observeOn(AndroidSchedulers.mainThread())    .doOnSubscribe(disposable -> {        //请求开始,当前在主线程回调    })    .doFinally(() -> {        //请求结束,当前在主线程回调    })    .as(RxLife.as(this))  //感知生命周期    .subscribe(pageList -> {        //乐成回调,当前在主线程回调    }, (OnError) error -> {        //失败回调,当前在主线程回调    });
复制代码
到这,请求三部曲介绍完毕,接着,将介绍别的常用的功能
3.4、初始化
  1. //设置debug模式,默以为false,设置为true后,发请求,过滤"RxHttp"能看到请求日记RxHttp.setDebug(boolean debug)//非必须,只能初始化一次,第二次将抛出非常RxHttp.init(OkHttpClient okHttpClient)//或者,调试模式下会有日记输出RxHttp.init(OkHttpClient okHttpClient, boolean debug)
复制代码
此步调好坏必须的,如必要添加拦截器等其他业务需求,则可调用init方法举行初始化,不初始化或者传入null即代表使用默认OkHttpClient对象,发起在Application中初始化,默认的OkHttpClient对象在HttpSender类中可以找到,如下:
  1. private static OkHttpClient getDefaultOkHttpClient() {                                  X509TrustManager trustAllCert = new X509TrustManagerImpl();                         SSLSocketFactory sslSocketFactory = new SSLSocketFactoryImpl(trustAllCert);         return new OkHttpClient.Builder()                                                       .connectTimeout(10, TimeUnit.SECONDS)                                               .readTimeout(10, TimeUnit.SECONDS)                                                  .writeTimeout(10, TimeUnit.SECONDS)                                                 .sslSocketFactory(sslSocketFactory, trustAllCert) //添加信托证书                          .hostnameVerifier((hostname, session) -> true) //忽略host验证                           .build();                                                                   }                                                                                   
复制代码
虽然初始化好坏必须的,但是发起各人传入自定义的OkHttpClient对象,一来,自定义的OkHttpClient能最大化满意自身的业务;二来,随着RxHttp版本的升级,默认的OkHttpClient可能会发生变革(虽然可能性很小),故发起自定义OkHttpClient对象传入RxHttp。
3.5、公共参数/请求头

RxHttp支持为所有的请求添加公共参数/请求头,固然,假如你盼望某个请求不添加公共参数/请求头,也是支持的,而且非常简单。如下:
  1. RxHttp.setOnParamAssembly(new Function() {    @Override    public Param apply(Param p) { //此方法在子线程中实行,即请求发起线程        Method method = p.getMethod();        if (method.isGet()) {     //可根据请求范例添加差别的参数        } else if (method.isPost()) {        }        return p.add("versionName", "1.0.0")//添加公共参数                .addHeader("deviceType", "android"); //添加公共请求头    }});
复制代码
我们必要调用RxHttp.setOnParamAssembly(Function)方法,并传入一个Function接口对象,每次发起请求,都会回调该接口。
固然,假如盼望某个请求不回调该接口,即不添加公共参数/请求头,则可以调用setAssemblyEnabled(boolean)方法,并传入false即可,如下:
  1. RxHttp.get("/service/...")       //get请求     .setAssemblyEnabled(false)   //设置是否添加公共参数/头部,默以为true        .asString()                  //返回字符串数据        .subscribe(s -> {            //这里的s为String范例        //请求乐成                                             }, throwable -> {                                          //请求失败                                             });                                                
复制代码
3.6、多域名/动态域名

3.6.1、多域名
现实开发中,我们常常会遇到多个域名的环境,此中1个为默认域名,别的为非默认域名,对于这种环境,RxHttp提供了@DefaultDomain()、@Domain()这两个注解来标明默认域名和非默认域名,如下:
  1. public class Url {    @DefaultDomain() //设置为默认域名    public static String baseUrl = "https://www.wanandroid.com/"        @Domain(name = "BaseUrlBaidu") //非默认域名,并取别名为BaseUrlBaidu    public static String baidu = "https://www.baidu.com/";        @Domain(name = "BaseUrlGoogle") //非默认域名,并取别名为BaseUrlGoogle    public static String google = "https://www.google.com/";}
复制代码
通过@Domain()注解标注非默认域名,就会在RxHttp类中天生setDomainToXxxIfAbsent()方法,此中Xxx就是注解中取的别名。
上面我们使用了两个@Domain()注解,此时(必要Rebuild一下项目)就会在RxHttp类中天生setDomainToBaseUrlBaiduIfAbsent()、setDomainToBaseUrlGoogleIfAbsent()这两方法,此时发请求,我们就可以使用指定的域名,如下:
  1. //使用默认域名,则无需添加任何额外代码//此时 url = "https://www.wanandroid.com/service/..." RxHttp.get("/service/...")    .asString()      .subscribe();    //手动输入域名,此时 url = "https://www.mi.com/service/..."RxHttp.get("https://www.mi.com/service/...")    .asString()      .subscribe();//手动输入域名时,若再次指定域名,则无效//此时 url = "https://www.mi.com/service/..."RxHttp.get("https://www.mi.com/service/...")    .setDomainToBaseUrlBaiduIfAbsent()  //此时指定Baidu域名无效    .asString()      .subscribe();    //使用谷歌域名,此时 url = "https://www.google.com/service/..."       RxHttp.get("/service/...")    .setDomainToBaseUrlGoogleIfAbsent() //指定使用Google域名    .asString()      .subscribe();
复制代码
通过以上案例,可以知道,RxHttp共有3种指定域名的方式,按优先级排名分别是:手动输入域名 > 指定非默认域名 > 使用默认域名。
3.6.2、动态域名
现实开发中,也会有动态域名切换的需求,如域名被封、或者必要根据服务端下发的域名去配置,这对于RxHttp来说简直就是 so easy !!! 我们只必要对BaseUrl重新赋值,此时发请求便会立刻见效,如下:
  1. //此时 url = "https://www.wanandroid.com/service/..."RxHttp.get("/service/...")    .asString()      .subscribe();    Url.baseUrl = "https://www.qq.com"; //动态更改默认域名,改完立刻见效,非默认域名同理//此时 url = "https://www.qq.com/service/..."RxHttp.get("/service/...")    .asString()      .subscribe();
复制代码
3.7、关闭请求

我们知道,在Activity/Fragment中发起请求,假如页面烧毁时,请求还未结束,就会有内存走漏的伤害,因此,我们必要在页面烧毁时,关闭一些还未完成的请求,RxHttp提供了两种关闭请求的方式,分别是主动+手动。
3.7.1、主动关闭请求
主动关闭请求,必要引入本人开源的另一个库RxLife,先来看看怎样用:
  1. //以下代码均在FragmentActivty/Fragment中调用RxHttp.postForm("/service/...")    .asString()    .as(RxLife.as(this)) //页面烧毁、主动关闭请求    .subscribe();    //或者RxHttp.postForm("/service/...")    .asString()    .as(RxLife.asOnMain(this)) //页面烧毁、主动关闭请求 而且在主线程回调观察者    .subscribe();//kotlin用户,请使用life或lifeOnMain方法,如下:RxHttp.postForm("/service/...")    .asString()    .life(this) //页面烧毁、主动关闭请求    .subscribe();    //或者RxHttp.postForm("/service/...")    .asString()    .lifeOnMain(this) //页面烧毁、主动关闭请求 而且在主线程回调观察者    .subscribe();
复制代码
上面的this为LifecycleOwner接口对象,我们的FragmentActivity/Fragment均实现了这个接口,所有我们在FragmentActivity/Fragment中可以直接传this。
对RxLife不了解的同砚请检察RxLife 史上最优雅的管理RxJava生命周期,这里不详细解说。
3.7.2、手动关闭请求
手动关闭请求,我们只必要在订阅回调的时间拿到Disposable对象,通过该对象可以判断请求是否结束,假如没有,就可以关闭请求,如下:
  1. //订阅回调,可以拿到Disposable对象Disposable disposable = RxHttp.get("/service/...")    .asString()      .subscribe(s -> {        //乐成回调    }, throwable -> {       //失败回调    });    if (!disposable.isDisposed()) {  //判断请求有没有结束    disposable.dispose();       //没有结束,则关闭请求}                              
复制代码
3.8、文件上传/下载/进度监听

RxHttp可以非常优雅的实现上传/下载及进度的监听,是骡子是马,拉出来溜溜
3.8.1上传
通过addFile系列方法添加文件,如下:
  1. RxHttp.postForm("/service/...") //发送Form表单情势的Post请求      .addFile("file1", new File("xxx/1.png"))  //添加单个文件          .addFile("fileList", new ArrayList())   //通过List对象,添加多个文件         .asString()                                          .subscribe(s -> {                                      //上传乐成                                         }, throwable -> {                                      //上传失败                                         });                                            
复制代码
通过asUpload系列方法监听上传进度,如下:
  1. RxHttp.postForm("/service/...") //发送Form表单情势的Post请求                                        .addFile("file1", new File("xxx/1.png"))                                             .addFile("file2", new File("xxx/2.png"))                                             .asUpload(progress -> {                                                                  //上传进度回调,0-100,仅在进度有更新时才会回调                                                          int currentProgress = progress.getProgress(); //当前进度 0-100                           long currentSize = progress.getCurrentSize(); //当前已上传的字节巨细                           long totalSize = progress.getTotalSize();     //要上传的总字节巨细                        }, AndroidSchedulers.mainThread())   //指定回调(进度/乐成/失败)线程,不指定,默认在请求所在线程回调                                               .subscribe(s -> {                                                                        //上传乐成                                                                           }, throwable -> {                                                                        //上传失败                                                                           });                                                                              
复制代码
可以看到,跟上传的代码相比,我们仅仅是使用了asUpload(Consumer, Scheduler)方法更换asString()方法,第一个参数是进度监听接口,每当进度有更新时,都会回调该接口,第二个参数是指定回调的线程,这里我们指定了在UI线程中回调。
3.8.2、下载
下载使用asDownload(String)方法,传入本地路径即可
  1.   //文件存储路径String destPath = getExternalCacheDir() + "/" + System.currentTimeMillis() + ".apk";RxHttp.get("http://update.9158.com/miaolive/Miaolive.apk")    .asDownload(destPath) //留意这里使用asDownload利用符,并传入本地路径    .subscribe(s -> {        //下载乐成,回调文件下载路径    }, throwable -> {        //下载失败    });
复制代码
3.8.3、带进度下载
带进度下载使用asDownload(String,Consumer,Scheduler)方法
  1.   //文件存储路径String destPath = getExternalCacheDir() + "/" + System.currentTimeMillis() + ".apk";RxHttp.get("http://update.9158.com/miaolive/Miaolive.apk")    .asDownload(destPath, progress -> {        //下载进度回调,0-100,仅在进度有更新时才会回调,最多回调101次,末了一次回调文件存储路径        int currentProgress = progress.getProgress(); //当前进度 0-100        long currentSize = progress.getCurrentSize(); //当前已下载的字节巨细        long totalSize = progress.getTotalSize();     //要下载的总字节巨细    }, AndroidSchedulers.mainThread()) //指定主线程回调    .subscribe(s -> {//s为String范例,这里为文件存储路径        //下载完成,处置处罚相干逻辑    }, throwable -> {        //下载失败,处置处罚相干逻辑    });
复制代码
3.8.4、断点下载
断点下载相较于下载,仅必要调用setRangeHeader(long startIndex, long endIndex)方法传入开始及结束位置即可(结束位置不传默以为文件末了),别的没有任何差别
  1. String destPath = getExternalCacheDir() + "/" + "Miaobo.apk";long length = new File(destPath).length(); //已下载的文件长度RxHttp.get("http://update.9158.com/miaolive/Miaolive.apk")    .setRangeHeader(length)  //设置开始下载位置,结束位置默以为文件末了    .asDownload(destPath)    .subscribe(s -> { //s为String范例        //下载乐成,处置处罚相干逻辑    }, throwable -> {        //下载失败,处置处罚相干逻辑    });
复制代码
3.8.5、带进度断点下载
带进度断点下载相较于带进度下载仅必要调用setRangeHeader方法传入开始及结束位置即可(结束位置不传默以为文件末了),别的没有任何差别
  1. String destPath = getExternalCacheDir() + "/" + "Miaobo.apk";long length = new File(destPath).length(); //已下载的文件长度RxHttp.get("http://update.9158.com/miaolive/Miaolive.apk")    .setRangeHeader(length)  //设置开始下载位置,结束位置默以为文件末了    .asDownload(destPath, progress -> {        //下载进度回调,0-100,仅在进度有更新时才会回调        int currentProgress = progress.getProgress(); //当前进度 0-100        long currentSize = progress.getCurrentSize(); //当前已下载的字节巨细        long totalSize = progress.getTotalSize();     //要下载的总字节巨细    }, AndroidSchedulers.mainThread()) //指定主线程回调    .subscribe(s -> { //s为String范例        //下载乐成,处置处罚相干逻辑    }, throwable -> {        //下载失败,处置处罚相干逻辑    });
复制代码
注:上面带进度断点下载中,返回的进度会从0开始,假如必要衔接前次下载的进度,则调用asDownload(String,long,Consumer,Scheduler)方法传入前次已经下载好的长度(第二个参数),如下:
  1. String destPath = getExternalCacheDir() + "/" + "Miaobo.apk";long length = new File(destPath).length(); //已下载的文件长度RxHttp.get("http://update.9158.com/miaolive/Miaolive.apk")    .setRangeHeader(length)  //设置开始下载位置,结束位置默以为文件末了    .asDownload(destPath, length, progress -> {        //下载进度回调,0-100,仅在进度有更新时才会回调        int currentProgress = progress.getProgress(); //当前进度 0-100        long currentSize = progress.getCurrentSize(); //当前已下载的字节巨细        long totalSize = progress.getTotalSize();     //要下载的总字节巨细    }, AndroidSchedulers.mainThread()) //指定主线程回调    .subscribe(s -> { //s为String范例        //下载乐成,处置处罚相干逻辑    }, throwable -> {        //下载失败,处置处罚相干逻辑    });
复制代码
3.9、超时设置

3.9.1、设置全局超时
RxHttp内部默认的读、写、毗连超时时间均为10s,如需修改,请自定义OkHttpClient对象,如下:
  1. //设置读、写、毗连超时时间为15sOkHttpClient client = new OkHttpClient.Builder()    .connectTimeout(15, TimeUnit.SECONDS)    .readTimeout(15, TimeUnit.SECONDS)    .writeTimeout(15, TimeUnit.SECONDS)    .build();RxHttp.init(client);
复制代码
3.9.2、为单个请求设置超时
为单个请求设置超时,使用的是RxJava的timeout(long timeout, TimeUnit timeUnit)方法,如下:
  1. RxHttp.get("/service/...")    .asString()    .timeout(5, TimeUnit.SECONDS)//设置总超时时间为5s    .as(RxLife.asOnMain(this))  //感知生命周期,并在主线程回调    .subscribe(pageList -> {        //乐成回调    }, (OnError) error -> {        //失败回调    });
复制代码
注:这里设置的总超时时间要小于全局读、写、毗连超时时间之和,否则无效
3.10、设置Converter

3.10.1、设置全局Converter
  1. IConverter converter = FastJsonConverter.create();RxHttp.setConverter(converter)
复制代码
3.10.2、为请求设置单独的Converter
起首必要在任意public类中通过@Converter注解声明Converter,如下:
  1. public class RxHttpManager {    @Converter(name = "XmlConverter") //指定Converter名称    public static IConverter xmlConverter = XmlConverter.create();}
复制代码
然后,rebuild 一下项目,就在主动在RxHttp类中天生setXmlConverter()方法,随后就可以调用此方法为单个请求指定Converter,如下:
  1. RxHttp.get("/service/...")    .setXmlConverter()   //指定使用XmlConverter,不指定,则使用全局的Converter    .asObject(NewsDataXml.class)    .as(RxLife.asOnMain(this))  //感知生命周期,并在主线程回调    .subscribe(dataXml -> {        //乐成回调    }, (OnError) error -> {        //失败回调    });
复制代码
3.11、请求加解密

3.11.1、加密
请求加密,必要自定义Param,非常简单,详情请检察本文5.2章节----自定义Param
3.11.2、解密
有些时间,请求会返回一大串的密文,此时就必要将密文转化为明文,直接来看代码,如下:
  1. //设置数据解密/解码器                                               RxHttp.setResultDecoder(new Function() {    //每次请求乐成,都会回调这里,并传入请求返回的密文       @Override                                                  public String apply(String s) throws Exception {           String plaintext = decode(s);   //将密文解密成明文,解密逻辑本身实现        return plaintext;    //返回明文                                       }                                                      });                                                        
复制代码
很简单,通过RxHttp.setResultDecoder(Function)静态方法,传入一个接口对象,此接口会在每次请求乐成的时间被回调,并传入请求返回的密文,只必要将密文解密后返回即可。
然而,有些请求是不需求解密的,此时就可以调用setDecoderEnabled(boolean)方法,并传入false即可,如下:
  1. RxHttp.get("/service/...")    .setDecoderEnabled(false)  //设置本次请求不必要解密,默以为true    .asString()    .subscribe(pageList -> {        //乐成回调    }, (OnError) error -> {        //失败回调    });
复制代码
3.12、指定请求/回调线程

RxHttp默认在Io线程实行请求,也默认在Io线程回调,即默认在同一Io线程实行请求并回调,固然,我们也可以指定请求/回调所在线程。
3.12.1、指定请求所在线程
我们可以调用一些列subscribeXxx方法指定请求所在线程,如下:
  1. //指定请求所在线程,必要在第二部曲前任意位置调用,第二部曲后调用无效RxHttp.get("/service/...")    .subscribeOnCurrent() //指定在当火线程实行请求,即同步实行,    .asString()      .subscribe();//别的subscribeXxx方法subscribeOnIo()   //RxHttp默认的请求线程subscribeOnSingle()subscribeOnNewThread()subscribeOnComputation()subscribeOnTrampoline()subscribeOn(Scheduler) //自定义请求线程
复制代码
以上使用的皆是RxJava的线程调度器,不熟悉的请自行查阅相干资料,这里不做详细介绍。
3.12.2、指定回调所在线程
指定回调所在线程,依然使用RxJava的线程调度器,如下:
  1. //指定回调所在线程,必要在第二部曲后调用RxHttp.get("/service/...")    .asString()      .observeOn(AndroidSchedulers.mainThread()) //指定在主线程回调    .subscribe(s -> { //s为String范例,主线程回调        //乐成回调    }, throwable -> {        //失败回调    });
复制代码
3.13、 Retrofit用户

时常会有童鞋问我,我是Retrofit用户,喜好把接口写在一个类里,然后可以直接调用,RxHttp怎样实现?着实,这个标题压根就不是标题,在介绍第二部曲的时间,我们知道,使用asXxx方法后,就会返回Observable对象,因此,我们就可以如许实现:
  1. public class HttpWrapper {    public static Observable getStudent(int page) {        return RxHttp.get("/service/...")            .add("page", page)            .asList(Student.class);    }}//随后在别的地方就可以直接调用HttpWrapper.getStudent(1)    .as(RxLife.asOnMain(this))  //主线程回调,并在页面烧毁主动关闭请求(假如还未关闭的话)    .subscribe(students -> { //学生列表        //乐成回调    }, throwable -> {        //失败回调    });
复制代码
很简单,封装的时间返回Observable对象即可。
另有的同砚问,我们获取列表的接口,页码是和url拼接在一起的,Retrofit可以通过占位符,那RxHttp又怎样实现?简单,如下:
  1. public class HttpWrapper {    //单个占位符    public static Observable getStudent(int page) {        return RxHttp.get("/service/%d/...", page)  //使用尺度的占位符协议            .asObject(Student.class);    }        //多个占位符    public static Observable getStudent(int page, int count) {        return RxHttp.get("/service/%1$d/%2$d/...", page, count)  //使用尺度的占位符协议            .asObject(Student.class);    }}
复制代码
这一点跟Retrofit差别,Retrofit是通过注解指定占位符的,而RxHttp是使用尺度的占位符,我们只必要在url中声明占位符,随后在传入url的反面,带上对应的参数即可。
4、原理分析

4.1、工作流程

在RxHttp有4个告急的脚色,分别是:

  • Param:RxHttp类中所有添加的参数/请求头/文件都交由它处置处罚,它终极目标就是为了构建一个Request对象
  • HttpSender :它负责从Param对象中拿到Request对象,从而实行请求,终极返回Response对象
  • Parser:它负责将HttpSender返回的Response对象,剖析成我们盼望的实体类对象,也就是泛型T
  • RxHttp:它像一个管家,指挥前面3个脚色做变乱,固然,它也有本身的变乱要做,好比:请求线程的调度,BaseUrl的处置处罚、允许开发者自定义API等等
为此,我画了一个流程图,可以直观的了解到RxHttp的大抵工作流程

我想应该很好明白,RxHttp要做的变乱,就是把添加的参数/请求头等全部丢给Param处置处罚,本身啥事也不敢;随后将Param交给HttpSender,让它去实行请求,实行完毕,返回Response对象;接着又将Response对象丢给Parser去做数据剖析工作,并返回实体类对象T;末了,将T通过回调传给开发者,到此,一个请求就处置处罚完成。
4.2、Param

起首,附上一张Param类的继承关系图

下面将从上往下对上图中的类做个简单的介绍:

  • IHeaders:接口类,里面定义了一系列addHeader方法
  • IParam:接口类,里面定义了add(String,Object)、addAll(Map)等方法,
  • IRequest:接口类,里面定义了一系列getXxx方法,通过这些方法终极构建一个Request对象
  • Param:接口类,是一个空接口,继承了前面3个接口,里面有一系列静态方法可以获取到Param的详细实现类
  • AbstractParam:Param接口的抽象实现类,实现了Param接口的所有方法
  • IFile:接口类,里面定义了一系列addFile方法
  • IUploadLengthLimit:接口类,里面就定义了一个checkLength()方法,用于限定文件上传巨细
  • NoBodyParam:Param的详细实现类,Get、Head请求就是通过该类去实现的
  • JsonParam:Param的详细实现类,调用RxHttp.xxxJson(String)请求方法时,内部就是通过该类去实现的
  • JsonArrayParam:Param的详细实现类,调用RxHttp.xxxJsonArray(String)请求方法时,内部就是通过该类去实现的
  • FormParam:Param的详细实现类,同时又实现了IFile、IUploadLengthLimit两个接口,调用RxHttp.xxxForm(String)请求方法时,内部就是通过该类去实现的
4.3、HttpSender

HttpSender可以把它明白为请求发送者,里面声明OkHttpClient对象和一系列静态方法,我们来简单看下:
  1. public final class HttpSender {    private static OkHttpClient mOkHttpClient; //只能初始化一次,第二次将抛出非常    //处置处罚化OkHttpClient对象    public static void init(OkHttpClient okHttpClient) {        if (mOkHttpClient != null)            throw new IllegalArgumentException("OkHttpClient can only be initialized once");        mOkHttpClient = okHttpClient;    }    //通过Param对象同步实行一个请求    public static Response execute(@NonNull Param param) throws IOException {        return newCall(param).execute();    }    static Call newCall(Param param) throws IOException {        return newCall(getOkHttpClient(), param);    }    //所有的请求,终极都会调此方法拿到Call对象,然后实行请求    static Call newCall(OkHttpClient client, Param param) throws IOException {        param = RxHttpPlugins.onParamAssembly(param);        if (param instanceof IUploadLengthLimit) {            ((IUploadLengthLimit) param).checkLength();        }        Request request = param.buildRequest();  //通过Param拿到Request对象        LogUtil.log(request);        return client.newCall(request);    }    //省略了部分方法}
复制代码
这里我们重点看下newCall(OkHttpClient, Param)方法,该方法第一行就是为Param添加公共参数;然后判断Param有没有实现IUploadLengthLimit接口,有的话,查抄文件上传巨细,超出巨细,则抛出IO非常;接着就是通过Param拿到Request对象;末了拿到Call对象,就可以发送一个请求。
4.4、Parser

先看下Parser继承布局图

这里对上图中的类做个简单的介绍

  • Parser:接口类,里面定义了一个T onParse(Response)方法,输入Response对象,输出实体类对象T
  • AbstractParser:抽象类,里面没有任何详细实现,告急作用是在构造方法内获取泛型范例
  • SimpleParser:是一个全能的剖析器,可以剖析任意数据布局,RxHttp内置的大部分asXxx方法,内部就是通过该剖析器实现的
  • ListParser:是一个列表剖析器,可以剖析任意列表数据,内置asList(Class)方法,就是通过该剖析器实现的
  • MapParser:是一个Map剖析器,可以剖析任意Map数据范例,内置的asMap系列方法,就是通过该剖析器实现的
  • BitmapParser:是一个Bitmap剖析器,通过该剖析器可以得到一个Bitmap对象,asBitmap()方法内部就是通过该剖析器实现的
  • DownloadParser:文件下载剖析器,用于文件下载,内置的一系列asDownload方法就是通过该剖析器实现的
5、扩展

5.1、自定义Parser

前面第二部曲中,我们介绍了一系列asXxx方法,通过该系列方法可以很方便的指定命据返回范例,特别是自定义的asResponse(Class)、asResponseList(Class)、asResponsePageList(Class)这3个方法,将Reponse范例数据,处置处罚的简直不要太完美,下面我们就来看看怎样自定义Parser。
源码永远是最好的学习方式,在学习自定义Parser前,我们不妨先看看内置的Parser是怎样实现的
SimPleParser
  1. public class SimpleParser extends AbstractParser {    //省略构造方法    @Override    public T onParse(Response response) throws IOException {        return convert(response, mType);    }}
复制代码
可以看到,SimpleParser除了构造方法,就剩一个onParser方法,该方法是在Parser接口中定义的,再来看看详细的实现convert(Response, Type),这个方法也是在Parser接口中定义的,而且有默认的实现,如下:
  1. public interface Parser {    //输入Response 输出T    T onParse(@NonNull Response response) throws IOException;    //对Http返回的效果,转换成我们盼望的实体类对象    default  R convert(Response response, Type type) throws IOException {        ResponseBody body = ExceptionHelper.throwIfFatal(response);  //这里内部会判断code=300 时,抛出非常        boolean onResultDecoder = isOnResultDecoder(response); //是否必要对返回的数据举行解密        LogUtil.log(response, onResultDecoder, null);        IConverter converter = getConverter(response);        //取出转换器        return converter.convert(body, type, onResultDecoder); //对数据进场转换    }    //省略若干方法}
复制代码
可以看到,非常的简单,输入Response对象和泛型范例Type,内部就通过IConverter接口转换为我们盼望的实体类对象并返回。
到这,我想各人应该就多少有点明确了,自定义Parser,无非就是继承AbstractParser,然后实现onParser方法即可,那我们来验证一下,我们来看看内置ListParser是不是如许实现的,如下:
  1. public class ListParser extends AbstractParser {    //省略构造方法    @Override    public List onParse(Response response) throws IOException {        final Type type = ParameterizedTypeImpl.get(List.class, mType); //拿到泛型范例        return convert(response, type);    }}
复制代码
可以看到,跟SimpleParser剖析器险些是一样的实现,差别是的,这里将我们输入的泛型T与List组拼为一个新的泛型范例,终极返回List对象。
如今,我们就可以来自定义Parser了,先来自定义ResponseParser,用来处置处罚Response数据范例,先看看数据布局:
  1. public class Response {    private int    code;    private String msg;    private T      data;    //这里省略get、set方法}
复制代码
自定义ResponseParser代码如下:
  1. //通过@Parser注解,为剖析器取别名为Response,此时就会在RxHttp类天生asResponse(Class)方法@Parser(name = "Response") public class ResponseParser extends AbstractParser {    //省略构造方法    @Override    public T onParse(okhttp3.Response response) throws IOException {        final Type type = ParameterizedTypeImpl.get(Response.class, mType); //获取泛型范例        Response data = convert(response, type);        T t = data.getData(); //获取data字段        if (data.getCode() != 0 || t == null) {//这里假设code不即是0,代表数据不精确,抛出非常            throw new ParseException(String.valueOf(data.getCode()), data.getMsg(), response);        }        return t;    }}
复制代码
可以看到,非常的简单,起首将我们输入泛型和自定义的Response类组拼成新的泛型范例,随后通过convert(Response, Type)方法得到Response对象,接着又对code及T做了判断,假如不精确就抛出非常,末了返回T。
估计这里有人会问,我怎么用这个剖析器呢?信任不少小同伴以及发现了,我们在ResponseParser类名上面用了@Parser注解,只要用了该注解,就会在RxHttp主动天生asXxx(Class)方法,此中Xxx就是我们在@Parser注解中为剖析器取的别名,这里取别名为Response,以是便会在RxHttp类中主动天生asResponse(Class)方法,如下:
  1.   public  Observable asResponse(Class type) {    return asParser(new ResponseParser(type));  }
复制代码
可以看到,该方法内部又调用了asParser(Parser)方法,并传入了ResponseParser,因此,我们有两种方式使用自定义的ResponseParser,如下:
  1. //第一种方式,使用@parser注解天生的asResponse方法RxHttp.postForm("/service/...")   //发送post表单请求    .add("key", "value")          //添加参数,可调用多次    .asResponse(Student.class)    //返回Student范例    .subscribe(student -> {           //请求乐成,这里能拿到 Student对象                   }, throwable -> {                 //请求失败                    });   //第二种方式,直接使用asParser(Parser)方法RxHttp.postForm("/service/...")   //发送post表单请求    .add("key", "value")          //添加参数,可调用多次    .asParser(new ResponseParser(){})    //返回Student范例    .subscribe(student -> {           //请求乐成,这里能拿到 Student对象                   }, throwable -> {                 //请求失败                    });  
复制代码
以上两种方式,除了写法上的区别,别的都一样,用哪种,看个人喜好,但还是发起使用第一种方式,不但写法简单,也低落了耦合。
这里末了再贴上ResponseListParser、ResponsePageListParser的源码,原理都是一样的,代码实现也差不多,就不再详解
ResponseListParser
  1. @Parser(name = "ResponseList")public class ResponseListParser extends AbstractParser {    //省略构造方法    @Override    public List onParse(okhttp3.Response response) throws IOException {        final Type type = ParameterizedTypeImpl.get(Response.class, List.class, mType); //获取泛型范例        Response data = convert(response, type);        List list = data.getData(); //获取data字段        if (data.getCode() != 0 || list == null) {  //code不即是0,阐明数据不精确,抛出非常            throw new ParseException(String.valueOf(data.getCode()), data.getMsg(), response);        }        return list;    }}
复制代码
ResponsePageListParser
  1. @Parser(name = "ResponsePageList")public class ResponsePageListParser extends AbstractParser {          //省略构造方法    @Override    public PageList onParse(okhttp3.Response response) throws IOException {        final Type type = ParameterizedTypeImpl.get(Response.class, PageList.class, mType); //获取泛型范例        Response data = convert(response, type);        PageList pageList = data.getData(); //获取data字段        if (data.getCode() != 0 || pageList == null) {  //code不即是0,阐明数据不精确,抛出非常            throw new ParseException(String.valueOf(data.getCode()), data.getMsg(), response);        }        return pageList;    }}
复制代码
5.2、自定义Param

自定义Param,想较于自定义Parser,要更加的简单,我们只需根据本身的需求,继承NoBodyParam、FormParam、JsonParam等,增加或者重写方法即可,好比我们有以下3种环境,必要自定义Param,如下:

  • postForm请求,必要将所有添加的参数,拼接在一起,随后加密,末了将加密的字符串添加到请求头中
  • postJson请求,必要将所有的参数,也就是json字符串加密后再发送出去
  • FormParam里面的API不敷用,我要自定义API
5.2.1、postForm请求加密

这种环境,我们必要继承FormParam,并重写getRequestBody()方法,如下:
  1. @Param(methodName = "postEncryptForm")public class PostEncryptFormParam extends FormParam {    public PostEncryptFormParam(String url) {        super(url, Method.POST);  //Method.POST代表post请求    }    @Override    public RequestBody getRequestBody() {        //这里拿到你添加的所有参数        List keyValuePairs = getKeyValuePairs();        String encryptStr = "加密后的字符串";  //根据上面拿到的参数,自行实现加密逻辑        addHeader("encryptStr", encryptStr);        return super.getRequestBody();    }}
复制代码
5.2.2、postJson请求加密

这种环境,我们必要继承JsonParam,也重写getRequestBody()方法,如下:
  1. @Param(methodName = "postEncryptJson")public class PostEncryptJsonParam extends JsonParam {    public PostEncryptFormParam(String url) {        super(url, Method.POST);    }    @Override    public RequestBody getRequestBody() {        //这里拿到你添加的所有参数        Map params = getParams();        String encryptStr = "加密后的字符串";  //根据上面拿到的参数,自行实现解密逻辑        return RequestBody.create(MEDIA_TYPE_JSON, encryptStr);  //发送加密后的字符串    }}
复制代码
5.2.3、自定义API

我们继承FormParam,并新增两个test方法`,如下:
  1. @Param(methodName = "postTestForm")public class PostTestFormParam extends FormParam {    public PostEncryptFormParam(String url) {        super(url, Method.POST);    }        public PostEncryptFormParam test(long a, float b) {        //这里的业务逻辑自行实现        return this;    }        public PostEncryptFormParam test1(String s, double b) {        //这里的业务逻辑自行实现        return this;    }}
复制代码
5.2.4、使用自定义的Param

同样的标题,我们怎么用这3个自定义的Param呢?我想大多数人在类名前发现类@Param注解,并为Param取了别名。那这个又有什么作用呢?
答案发表,只要在自定的Param上使用了@Param注解,并取了别名,就会在RxHttp类主动天生一个跟别名一样的方法,在上面我们自定义了3个Param,并分别取别名为postEncryptForm、postEncryptJson、postTestForm,此时就会在RxHttp类中天生postEncryptForm(String)、postEncryptJsonString)、postTestForm(String)这3个方法,我们在RxHttp这个类中来看下:
  1.   public static RxHttp$PostEncryptFormParam postEncryptForm(String url) {    return new RxHttp$PostEncryptFormParam(new PostEncryptFormParam(url));  }    public static RxHttp$PostEncryptJsonParam postEncryptJson(String url) {    return new RxHttp$PostEncryptJsonParam(new PostEncryptJsonParam(url));  }  public static RxHttp$PostTestFormParam postTestForm(String url) {    return new RxHttp$PostTestFormParam(new PostTestFormParam(url));  }
复制代码
发请求时,只必要调用对应的方法就好,如:
  1. //发送加密的postForm请求RxHttp.postEncryptForm("/service/...")       .add("key", "value")          //添加参数,可调用多次    .asString()                  //返回String范例    .subscribe(s-> {           //请求乐成        }, throwable -> {                 //请求失败                    });      //发送加密的postJson请求RxHttp.postEncryptJson("/service/...")       .add("key", "value")          //添加参数,可调用多次    .asString()                  //返回String范例    .subscribe(s-> {           //请求乐成        }, throwable -> {                 //请求失败                    });  
复制代码
那我自定义的API怎样调用呢,so easy!!!!,选择对应的请求方法后,就可以直接调用,如下:
  1. //发送加密的postJson请求RxHttp.postTestJson("/service/...")       .test(100L, 99.99F)          //调用自定义的API    .test1("testKey", 88.88D)    //调用自定义的API    .add("key", "value")         //添加参数,可调用多次    .asString()                  //返回String范例    .subscribe(s-> {           //请求乐成        }, throwable -> {                 //请求失败                    });  
复制代码
5.3、自定义Converter

RxHttp内部默认使用来GsonConverter,而且额外提供了4个Converter,如下:
  1. //非必须 根据本身需求选择Converter  RxHttp默认内置了GsonConverterimplementation 'com.rxjava.rxhttp:converter-jackson:1.3.6'implementation 'com.rxjava.rxhttp:converter-fastjson:1.3.6'implementation 'com.rxjava.rxhttp:converter-protobuf:1.3.6'implementation 'com.rxjava.rxhttp:converter-simplexml:1.3.6'
复制代码
5.3.1、自定义TestConverter

即使如许,RxHttp也无法包管满意所有的业务需求,为此,我们可以选择自定义Converter,自定义Converter必要继承IConverter接口,如下:
  1. public class TestConverter implements IConverter {    /**     * 请求乐成后会被回调     * @param body             ResponseBody     * @param type             泛型范例     * @param onResultDecoder  是否必要对效果举行解码/解密     */    @Override    public  T convert(ResponseBody body, Type type, boolean onResultDecoder) throws IOException {        //自行实现相干逻辑        return null;    }    /**     * json请求前会被回调,必要自行根据泛型T创建RequestBody对象,并返回     */    @Override    public  RequestBody convert(T value) throws IOException {        //自行实现相干逻辑        return null;    }}
复制代码
以上两个convert方法根据自身业务需求自行实现,可以参考RxHttp提供FastJsonConverter、SimpleXmlConverter等Converter
5.3.2、怎么用Converter

请检察本文3.10章节----设置Converter
6、小本领

在这教各人一个小本领,由于使用RxHttp发送请求都遵照请求三部曲,故我们可以在android studio 设置代码模版,如下

如图设置好后,写代码时,输入rp,就会主动天生模版,如下:

7、小结

到这,RxHttp常勤奋能介绍完毕,你会发现,齐备都是那么的优美,无论你是get、post、加密请求、自定义剖析器,还是文件上传/下载/进度监听等等,皆遵照请求三部曲。特别是对Response范例数据处置处罚,可以说是天衣无缝,我们无需每次都判断code,直接就可以拿到T,简直了。。。
末了,喜好的,请给本文点个赞,假如可以,还请给个star,创作不易,感激不尽。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|深圳论坛-深圳人的网上家园  

GMT+8, 2020-10-1 23:40 , Processed in 0.112742 second(s), 30 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表