Disposable disposable = HttpSender.from(param)
.subscribe(s -> { //这里的s为String类型,即Http请求的返回结果
//成功回调
}, throwable -> {
//失败回调
});
`疑问:说好的一条链发送请求呢?别着急,还没到放大招的时候` 到这,我可以告诉大家,`Param`承担的是一个请求体的一个角色,我们通过`Param`可以确定请求方式(如:Get、Post、Put、Delete等请求方式)、添加请求参数、添加请求头、添加File对象等;然后通过HttpSender,传入`Param`对象,将请求发送出去。
## HttpSender
到这,有人又有疑问,前面初始化、设置公共参数都用到了HttpSender,这里发送请求又用到了HttpSender ,那么它又是承担怎么样的一个角色呢?看名字,我们可以理解为它就是一个请求发送者,通过一个`from`操作符,传入一个`Param`对象,然后返回一个`RxJava`的`Observable`对象,此时,我们就可以使用RxJava强大的操作符去处理相关的逻辑(这就是简介说的,做到了与RxJava的无缝链接),在这,我们只是使用了`subscribe`操作符去订阅观察者。
## RxHttp
现在,我们正式放大招,标题说好的一条链发送请求,既然吹牛了,就要去实现它。拿上面的例子,看看我们如何一条链实现,上代码
RxHttp.get(“http://…”)
.add(“key”, “value”)
.from()
.subscribe(s -> { //这里的s为String类型,即Http请求的返回结果
//成功回调
}, throwable -> {
//失败回调
});
我们的主角[RxHttp]( )终于登场了,可以看到使用RxHttp类我们就实现了一条链完成请求的发送,那它又是承担一个什么角色呢?我们暂时可以理解为`RxHttp=Param+HttpSender`,并且还有自己特殊的使命。至于什么使用,后面会讲解。
我们现在来解疑惑,为什么我们的库叫`RxHttp`,但是初始化、设置公共参数等却用HttpSender?因为`RxHttp`这个类不在RxHttp库中,它是通过注解处理器生成的类。前面我们看到gradle依赖时,使用了
annotationProcessor ‘com.rxjava.rxhttp:rxhttp-compiler:1.0.1’
该注解处理器的目的就是在项目中生成RxHttp类,那为何不直接把它写到库里面去呢?前面讲过,因为它有自己的使命,而这个使命,在RxHttp库里无法完成。
接下来,我们来看看,如何发送Post请求、如何在Activity/Fragment销毁时,自动关闭为完成的请求、如何上传/下载文件及进度的监听、如何把Http返回的结果自动解析成我们想要的对象。
`注:`以下讲解均使用RxHttp
## Post
RxHttp.postForm(“http://…”)
.add(“key”, “value”)
.from()
.subscribe(s -> { //这里的s为String类型,即Http请求的返回结果
//成功回调
}, throwable -> {
//失败回调
});
可以看到,跟上面的Get请求只有一点不同,Get是`RxHttp.get`,而Post是`RxHttp.postForm`,除此之外,没有任何区别,我们在看来来,RxHttp都有哪些静态方法供我们选择请求方式
![](https://upload-images.jianshu.io/upload_images/15233854-43feb9c6e1faee64.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可以看到,默认提供了10个静态方法供我们选择具体的请求方式,有Get、Post、Put等,而Post等又分为postForm和postJson,这个好理解,前者是发送表单形式的post请求,后者是发送json字符串的post请求。
现实中,这些默认的请求方式显然不能满足我们的需求,如:我要发送加密的post请求,这个时候该怎么办呢?此时就需要我们自定义请求方式。
## Activity 销毁,自动关闭未完成的请求
上面的案例中,在Activity/Fragment销毁时,如果请求还未完成,就会造成Activity/Fragment 无法回收,导致内存泄漏。这是非常严重的问题,那么`RxHttp`是如何解决的呢?此时,就要引入我自己写的另一个库[RxLife]( ),直接看看如何使用
RxHttp.postForm(“http://…”)
.add(“key”, “value”)
.from()
.as(RxLife.as(this)) //订阅观察者前,加上这句话即可
.subscribe(s -> {
//成功回调
}, throwable -> {
//失败回调
});
//或者
RxHttp.postForm(“http://…”)
.add(“key”, “value”)
.from()
.as(RxLife.asOnMain(this)) //asOnMain 可以在主线程回调观察者
.subscribe(s -> {
//成功回调
}, throwable -> {
//失败回调
});
这里的`this`为`LifecycleOwner`对象,它是一个接口,这里我们传入的是Activity,因为Activity实现了`LifecycleOwner`接口。当Activity/Fragment销毁时,会将RxJava的管道中断,管道中断时,又会将未完成的请求自动关闭。 在下面的讲解中,我们均会使用RxLife
## 文件上传/下载及进度监听
使用`RxHttp`,可以很优雅的实现文件上传/下载及进度的监听,如何优雅?直接上代码
### 文件上传
RxHttp.postForm(“http://…”) //发送Form表单形式的Post请求
.add(“key”, “value”)
.add(“file1”, new File(“xxx/1.png”)) //添加file对象
.add(“file2”, new File(“xxx/2.png”))
.from() //from操作符,是异步操作
.as(RxLife.asOnMain(this)) //感知生命周期,并在主线程回调
.subscribe(s -> {
//成功回调
}, throwable -> {
//失败回调
});
可以看到,文件上传跟普通的post请求其实没啥区别,无非就是在post请求的基础上,调用add方法添加要上传的文件对象。
### 文件下载
//文件存储路径
String destPath = getExternalCacheDir() + “/” + System.currentTimeMillis() + “.apk”;
RxHttp.get(“http://update.9158.com/miaolive/Miaolive.apk”)
.download(destPath) //注意这里使用download操作符,并传入本地路径
.as(RxLife.asOnMain(this)) //感知生命周期,并在主线程回调
.subscribe(s -> {
//下载成功,回调文件下载路径
}, throwable -> {
//下载失败
});
下载跟普通请求不同的是,下载使用的是`download`操作符,其它都一样。
### 文件下载进度监听
//文件存储路径
String destPath = getExternalCacheDir() + “/” + System.currentTimeMillis() + “.apk”;
RxHttp.get(“http://update.9158.com/miaolive/Miaolive.apk”)
.downloadProgress(destPath) //注:如果需要监听下载进度,使用downloadProgress操作符
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(progress -> {
//下载进度回调,0-100,仅在进度有更新时才会回调,最多回调101次,最后一次回调文件存储路径
int currentProgress = progress.getProgress(); //当前进度 0-100
long currentSize = progress.getCurrentSize(); //当前已下载的字节大小
long totalSize = progress.getTotalSize(); //要下载的总字节大小
String filePath = progress.getResult(); //文件存储路径,最后一次回调才有内容
})
.filter(Progress::isCompleted)//下载完成,才继续往下走
.map(Progress::getResult) //到这,说明下载完成,返回下载目标路径
.as(RxLife.as(this)) //感知生命周期
.subscribe(s -> {//s为String类型,这里为文件存储路径
//下载完成,处理相关逻辑
}, throwable -> {
//下载失败,处理相关逻辑
});
下载进度的监听我们稍微看一下 ,首先一点,下载使用`download`操作符,而下载进度监听使用`downloadProgress`操作符,随后,我们使用了`doOnNext`操作符处理进度回调,注意这里是仅当有进度更新时,才会回调,其中的`progress`变量是一个`Progress`类型的对象,我们贴上源码:
public class Progress {
private int progress; //当前进度 0-100
private long currentSize;//当前已完成的字节大小
private long totalSize; //总字节大小
private T mResult; //http返回结果,上传/下载完成时调用
//省略get/set方法
}
由于进度回调会执行101次(上面注释有解释),而最下面观察者其实是不需要关心这么多事件的,只需要关心最后下载完成的事件,所以使用了`filter`操作符过滤事件,只要还未下载完成,就将事件过滤调,不让往下走。最终下载完成后,拿到本地下载路径。
### 文件上传进度监听
RxHttp.postForm(“http://www…”) //发送Form表单形式的Post请求
.add(“file1”, new File(“xxx/1.png”))
.add(“file2”, new File(“xxx/2.png”))
.add(“key1”, “value1”)//添加参数,非必须
.add(“key2”, “value2”)//添加参数,非必须
.addHeader(“versionCode”, “100”) //添加请求头,非必须
.uploadProgress() //注:如果需要监听上传进度,使用uploadProgress操作符
.observeOn(AndroidSchedulers.mainThread()) //主线程回调
.doOnNext(progress -> {
//上传进度回调,0-100,仅在进度有更新时才会回调,最多回调101次,最后一次回调Http执行结果
int currentProgress = progress.getProgress(); //当前进度 0-100
long currentSize = progress.getCurrentSize(); //当前已上传的字节大小
long totalSize = progress.getTotalSize(); //要上传的总字节大小
String result = progress.getResult(); //Http执行结果,最后一次回调才有内容
})
.filter(Progress::isCompleted)//过滤事件,上传完成,才继续往下走
.map(Progress::getResult) //到这,说明上传完成,拿到Http返回结果并继续往下走
.as(RxLife.as(this)) //感知生命周期
.subscribe(s -> { //s为String类型,由SimpleParser类里面的泛型决定的
//上传成功,处理相关逻辑
}, throwable -> {
//上传失败,处理相关逻辑
});
上传进度监听使用`downloadProgress`操作符,剩下的操作跟下载进度监听的操作都一样,通过`doOnNext`监听上传进度,然后过滤事件,最终拿到Http的返回结果。
### 数据解析器Parser
在上面的案例中,观察者拿到数据类型都是String类型,然后现实开发中,我们经常需要对数据解析成我们想要的对象,`RxHttp`考虑到了这一点,现在我们就来看看如何的到我们想要的对象
我们拿淘宝获取IP的接口作为测试接口`http://ip.taobao.com/service/getIpInfo.php?ip=63.223.108.42` 对应的数据结构如下
public class Response {
private int code;
private Address data;
//省略set、get方法
class Address {
//为简单起见,省略了部分字段
private String country; //国家
private String region; //地区
private String city; //城市
//省略set、get方法
}
}
开始发送请求
RxHttp.get(“http://ip.taobao.com/service/getIpInfo.php”) //Get请求
.add(“ip”, “63.223.108.42”)//添加参数
.addHeader(“accept”, “/”) //添加请求头
.addHeader(“connection”, “Keep-Alive”)
.addHeader(“user-agent”, “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)”)
.fromSimpleParser(Response.class) //这里返回Observable 对象
.as(RxLife.asOnMain(this)) //感知生命周期,并在主线程回调
.subscribe(response -> {
//成功回调
}, throwable -> {
//失败回调
});
可以看到,这里我们没有用`from`操作符,而是用了`fromSimpleParser`操作符,并且传入`Response.class`,最后观察者拿到的response变量就是Response类型的对象。怎么样,是不是很简单。RxHttp为我们提供了一系列的fromXXX方法,我们来看一下:
![](https://img-blog.csdnimg.cn/img_convert/669d979f943862aa3e673b279ca65984.png)
我们可以看到,一些基本类型的封装对象RxHttp都为我们封装好了,还有一个`fromListParser`方法,此方法是用来解析集合对象的,一些常见的数据结构,RxHttp都为我们考虑到了,并封装好了,然后,一些不常见的数据呢?眼尖的你也许发现了,上图中还有一个` Observable from(Parser parser)`方法,它允许我们传入一个自定义的解析器。
## 文末
那么对于想坚持程序员这行的真的就一点希望都没有吗?
其实不然,在互联网的大浪淘沙之下,留下的永远是最优秀的,我们考虑的不是哪个行业差哪个行业难,就逃避掉这些,无论哪个行业,都会有他的问题,但是无论哪个行业都会有站在最顶端的那群人。我们要做的就是努力提升自己,让自己站在最顶端,学历不够那就去读,知识不够那就去学。人之所以为人,不就是有解决问题的能力吗?挡住自己的由于只有自己。
**Android希望=技能+面试**
**[CodeChina开源项目地址:https://codechina.csdn.net/m0_60958482/android_p7](https://codechina.csdn.net/m0_60958482/android_p7)**
* **技能**
![](https://img-blog.csdnimg.cn/img_convert/c876cceaf7cd586bacb0ff7204125d5a.png)
* **面试技巧+面试题**
去学。人之所以为人,不就是有解决问题的能力吗?挡住自己的由于只有自己。
**Android希望=技能+面试**
**[CodeChina开源项目地址:https://codechina.csdn.net/m0_60958482/android_p7](https://codechina.csdn.net/m0_60958482/android_p7)**
* **技能**
[外链图片转存中...(img-jTLOrzsB-1630585679613)]
* **面试技巧+面试题**
![](https://img-blog.csdnimg.cn/img_convert/3655b2bf5f0eb3513638f3b560dd6a01.png)