前面我们对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 { /** * <p>添加文件对象 * <P>默认不支持,如有需要,自行扩展,参考{@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
转载请注明出处,谢谢:pray: 注解使用请查看
RxHttp 一条链发送请求之注解处理器 Generated API(四)