前面我们对RxHttp做了整体的介绍,我们知道,使用RxHttp库发送请求,有两种方式。一种通过Param+HttpSender的形式,另外一种是直接使用RxHttp类,而RxHttp类内部其实就是通过Param+HttpSender实现的,我们可以理解为RxHttp类是Param的代理类。为此,本文将详细讲解Param类。
如果还未阅读前面两篇文章,请查看
RxHttp 一条链发送请求,新一代Http请求神器(一)
RxHttp 一条链发送请求之强大的数据解析功能(二)
RxHttp库已更新至1.0.3版本,详情请查看RxHttp 源码
首先,附上一张Param类的继承关系图,下图中蓝色标注的为接口类。
下面将对上图中的常用类及方法做介绍。
在前文中,我们介绍了RxHttp的请求三部曲,如下:
RxHttp.get("http://...") //第一步,确定请求方式
.fromSimpleParser(String.class) // 第二步,确定解析器
.subscribe(s -> { //第三部 订阅观察者
//成功回调
}, throwable -> {
//失败回调
});
而其中第一步,内部其实就是操作Param类,在这一步,我们不仅可以选择请求方式,还可以添加参数、添加请求头、添加文件对象等常用的操作,下面详细讲解。
首先,我们来看看Param都给我们提供了哪些请求方式:
上图为Param提供的一系列静态方法,看名字应该也能知道,其中get
方法对应的就是Get
请求,同理postXxx
、putXxx
等方法就是对应的Post
、Put
等请求,而考虑到Post
等请求又可以有不同的形式,故提供了postForm
、postJson
方法,其中前者是表单形式,后者是Json形式。现实开发中,如果还有其它的形式的请求(如:发送加密的请求),就需要我们自定义Param类,以满足我们的业务需求,后续会讲解。
现在我们来看看Param是怎么定义的:
public interface Param extends ParamBuilder, HeadersBuilder, NoBodyRequest, RequestBuilder {
//Get请求
static Param get(@NonNull String url) {
return GetParam.with(url);
}
//Post请求,参数以Form表单键值对的形式提交
static Param postForm(@NonNull String url) {
return PostFormParam.with(url);
}
//省略其它方法
}
可以看到Param就是一个接口,并且继承了ParamBuilder、HeadersBuilder、NoBodyRequest、RequestBuilder这四个接口
确定了请求方式后,我们就需要添加请求参数,RxHttp提供了3个方法:
//对参数的操作都在此接口里
public interface ParamBuilder {
//添加单个参数
Param add(String key, Object value);
//通过map添加多个参数
Param add(Map<? extends String, ?> map);
//设置json字符串参数,调用此方法后,通过上面两个add方法添加的参数将失效;非Json请求调用此方法无任何作用
Param setJsonParams(String jsonParams);
//省略若干方法
}
第一个是添加单个参数,其中value是Object类型,故我们可以添加任意类型的参数,而不用进行强转(这一点对于强迫症患者的我,真的很实用);第二个是通过map对象添加多个参数;第三个方法setJsonParams
仅对Json形式的请求生效,如:postJson
、putJson
、patchJson
、deleteJson
,此方法有两点需要注意:
注:
Param 内部是通过LinkedHashMap存储参数。
对请求头的操作,都封装在一个接口里,代码如下:
public interface HeadersBuilder {
Headers getHeaders();
String getHeader(String key);
Headers.Builder getHeadersBuilder();
Param setHeadersBuilder(Headers.Builder builder);
Param addHeader(String key, String value);
Param addHeader(String line);
Param setHeader(String key, String value);
Param removeAllHeader(String key);
}
在上面的Headers
及Headers.Builder
都是OkHttp内部提供的类,故可以知道在Param内部是通过Headers.Builder
存储的请求头信息。
Param内部目前仅提供了一个添加文件的方法,如下:
//对参数的操作都在此接口里
public interface ParamBuilder {
/**
* 添加文件对象
*
默认不支持,如有需要,自行扩展,参考{@link PostFormParam}
*
* @param key 键
* @param file 文件对象
* @return Param
*/
default Param add(String key, File file) {
throw new UnsupportedOperationException("Please override if you need");
}
//省略若干方法
}
可以看到,此方法默认会抛出一个UnsupportedOperationException
异常,即代表不支持这个操作,如果要支持,需要重写此方法。目前RxHttp内部仅有postForm
请求重写了此方法,故仅有postForm
请求支持文件上传,其它请求调用此方法,将直接抛出异常;若自定义的请求要支持文件上传,请重写此方法。
我们知道,要拿到Param对象就必须调用相关静态方法,并传入url。然后现实开发中,我们可能需要动态更改url,又或者我们需要拿到当前url做一些判断,为此RxHttp提供了相关方法,我们来看看
public interface ParamBuilder {
Param setUrl(@NonNull String url);
}
public interface NoBodyRequest {
/**
* @return 带参数的url
*/
String getUrl();
/**
* @return 不带参数的url
*/
String getSimpleUrl();
//省略相关方法
}
setUrl
好理解,传入一个url即可,需要特别说明的是getUrl
、getSimpleUrl
方法,其中前者会将参数以Get请求的形式拼接在url后面,并返回;而后者仅返回我们传入的url对象。(在RxHttp库内部,Get、Head请求会调用getUrl方法,其它请求皆调用getSimpleUrl方法)
从上面的结构图,我们可以看到,RxHttp内部提供了10个类,不同形式及方式的请求,然后,现实开发中,它并不能满足我们的业务场景,此时就需要我们自定义Param。看上图我们知道,所有Param的具体实现类,都间接继承与AbstractParam
类,而对于同一种请求,例如PostFormParam
、PostJsonParam
都继承于AbstractPostParam
。因此,我们要自定义Param,可以继承AbstractXxxParam类即可。
例如,我们现在要实现一个Post请求,参数以加密后的Json字符串发出,代码就可以这些写
public class PostEncryptJsonParam extends AbstractPostParam {
public PostEncryptJsonParam(String url) {
super(url);
}
/**
* @return 根据自己的业务需求返回对应的RequestBody
*/
@Override
public RequestBody getRequestBody() {
return null;
}
}
可以看到,我们只需要实现一个getRequestBody()方法,并返回一个RequestBody对象即可,我们再来看看实现
@Param(methodName = "postEncryptJson")
public class PostEncryptJsonParam extends AbstractPostParam {
private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json;charset=utf-8");
public PostEncryptJsonParam(String url) {
super(url);
}
/**
* @return 根据自己的业务需求返回对应的RequestBody
*/
@Override
public RequestBody getRequestBody() {
//我们要发送Post请求,参数以加密后的json形式发出
//第一步,将参数转换为Json字符串
JsonObject jsonObject = BuildUtil.mapToJson(this);
String json = jsonObject.toString();
//第二步,加密
byte[] encryptByte = encrypt(json, "RxHttp");
//第三部,创建RequestBody并返回
RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, encryptByte);
return requestBody;
}
/**
* @param content 要加密的字符串
* @param password 密码
* @return 加密后的字节数组
*/
private byte[] encrypt(String content, String password) {
//加密代码省略
return null;
}
}
可以看到,非常简单,首先将参数转换为Json字符串,然后进行加密,最后根据加密后的数据创建RequestBody对象并返回即可,现在我们来看看如何使用PostEncryptJsonParam这个类。
注:
我们在PostEncryptJsonParam
类上使用了注解@Param(methodName = "postEncryptJson")
,Rebuild一下项目,就会在RxHttp类下生成一个static RxHttp postEncryptJson(String url)
的静态方法。
关于注解的使用,请查看RxHttp 扩展篇之注解处理器 Generated API(八)
此时我们就可以这么做
String url = "http://www....";
RxHttp.postEncryptJson(url) //postEncryptJson 是使用注解生成的方法
.add("key1", "value1")
.add("key2", "value3")//添加参数
.fromDataParser(Address.class) //from操作符,是异步操作
.as(RxLife.asOnMain(this)) //感知生命周期,并在主线程回调
.subscribe(address -> {
//accept方法参数类型由上面DataParser传入的泛型类型决定
//走到这里说明Http请求成功,并且数据正确
}, throwable -> {
//Http请求出现异常,有可能是网络异常,数据异常等
});
可以看到,使用RxHttp.postEncryptJson(url)
静态方法得到PostEncryptJsonParam对象,并添加相关参数即可,其它逻辑没有任何改变。
到这,我可以告诉你,AbstractPostParam、AbstractPutParam、AbstractPatchParam、AbstractDeleteParam这4个抽象类,其实是一样的逻辑,都只需要实现getRequestBody()方法即可。
到这,你会发现,Param在RxHttp库中是一个非常重要的角色,它提供了非常多简单易用的Api,这使得RxHttp非常的好用。
最后,本文如果有写的不对的地方,请广大读者指出。
如果觉得我写的不错,记得给我点赞RxHttp
转载请注明出处,谢谢?
注解使用请查看
RxHttp 一条链发送请求之注解处理器 Generated API(四)