前言
RxHttp截止 v2.2.7版本,共提供了6个注解,分别是@DefaultDomain
、@Domain
、@OkClient
、@Converter
、@Parser
、@Param
,接下来将一一介绍。
RxHttp库已更新至2.2.7版本,详情请查看RxHttp 源码
Gradle 依赖
implementation 'com.rxjava.rxhttp:rxhttp:2.2.7'
//rxhttp v2.2.2版本起,需要手动依赖okhttp
implementation 'com.squareup.okhttp3:okhttp:4.7.2'
//注解处理器,生成RxHttp类
annotationProcessor 'com.rxjava.rxhttp:rxhttp-compiler:2.2.7'
RxHttp 6个注解介绍
@DefaultDomain
该注解用于指定所有请求使用的默认域名,如下
public class Url {
@DefaultDomain() //设置为默认域名
public static String baseUrl = "https://www.wanandroid.com/";
}
此时发请求传入相对路径即可,如下:
RxHttp.get("/article/list/0/json")
.asString()
.subscribe(s -> { //这里的s为String类型,即Http请求的返回结果
//成功回调
}, throwable -> {
//失败回调
});
RxHttp在发送请求前,会对url做判断,如果没有域名,就会自动加上@DefaultDomain
注解指定的默认域名
@Domain
该注解用于指定非默认域名,如下:
public class Url {
@Domain(name = "Google") //设置非默认域名,name 可不传,不传默认为变量的名称
public static String googleUrl = "https://www.google.com";
@DefaultDomain() //设置为默认域名
public static String baseUrl = "https://www.wanandroid.com/";
}
此时再rebuild一下项目,就会在RxHttp类中生成一个setDomainToGoogleIfAbsent()
方法,其中的Google
字符就是name
指定的名字,然后发请求就可以这样:
RxHttp.get("/article/list/0/json")
.setDomainToGoogleIfAbsent()
.add("key", "value")
.asString()
.subscribe(s -> { //这里的s为String类型,即Http请求的返回结果
//成功回调
}, throwable -> {
//失败回调
});
//此时,完整的url为:https://www.google.com/article/list/0/json
setDomainToGoogleIfAbsent
方法内部会首先会判断我们传入的url有无域名,如果没有,就会加上我们指定的域名。
以上,可以看出,我们有3个种方式设置域名,第一种是传入的url直接带上域名;第二种使用@DefaultDomain
注解指定默认的域名;第三种使用@Domain
指定非默认域名,这三种优先界别如下:
url带上域名 > @Domain > @DefaultDomain
,其中@DefaultDomain
注解优先级别最低。
注意,接下来要放大招了。。。。。
对于非默认域名,每次都要调用setDomainXxx
方法才会生效,接口不多还好,多了,这种写法着实不太优雅,怎么办?
@Domain
注解,其实还有一个className
字段,通过指定该字段,可以生成一个RxHttp的包装类,使用该类发请求,就会默认使用@Domain
注解指定的baseurl,而无需调用setDomainXxx
方法,用法如下:
public class Url {
@Domain(name = "Google",className = "Simple")
public static String googleUrl = "https://www.google.com";
@DefaultDomain() //设置为默认域名
public static String baseUrl = "https://www.wanandroid.com/";
}
此时Rebuild一下项目,就会生成一个RxSimpleHttp
类,命名方法为:Rx+{className字段值}+Http
,此时,我们通过RxSimpleHttp
类发请求,就无需再指定非默认域名,如下:
RxSimpleHttp.get("/article/list/0/json")
.add("key", "value")
.asString()
.subscribe(s -> { //这里的s为String类型,即Http请求的返回结果
//成功回调
}, throwable -> {
//失败回调
});
//此时,完整的url为:https://www.google.com/article/list/0/json
扩展:动态域名
也许你已经注意到了,@DefaultDomain
及@Domain
注解修饰的常量,并没有使用final
关键字,这意味着我们可直接修改这些常量,以满足动态域名的需求,如下:
//动态更改默认域名,改为立即生效
Url.baseUrl = "https://www.baidu.com/"
RxHttp.get("/article/list/0/json")
.asString()
.subscribe(s -> { //这里的s为String类型,即Http请求的返回结果
//成功回调
}, throwable -> {
//失败回调
});
//此时,完整的url为:https://www.baidu.com/article/list/0/json
@OkClient
该注解,可以为某个请求指定单独的OkHttpClient
对象,如下:
public class RxHttpManager {
@OkClient(name = "BaiduClient")
public static OkHttpClient baiduClient = new OkHttpClient.Builder().build();
}
此时Rebuild一下项目,就会在RxHttp
类下生成setSimpleClient()
方法,发请求时,调用该方法,就会使用@OkClient
注解指定的OkHttpClient
对象执行请求,如下:
RxHttp.get("/article/list/0/json")
.setBaiduClient()
.asString()
.subscribe(s -> { //这里的s为String类型,即Http请求的返回结果
//成功回调
}, throwable -> {
//失败回调
});
以上代码,将使用指定的OkHttpClient
对象执行请求,如未指定,将使用默认的OkHttpClient
对象。
同样的,如果请求多了,这种写法着实不优雅,此时,也许你想起了@Domain
注解的className
字段,没错,@OkClient
注解也有该字段,如下:
public class RxHttpManager {
@OkClient(name = "BaiduClient",className = "Baidu")
public static OkHttpClient baiduClient = new OkHttpClient.Builder().build();
}
此时Rebuild一下项目,就是生成RxBaiduHttp
类,该类将默认使用@OkClient
注解指定的OkHttpClient
对象执行请求,通过该类发请求就无需指定OkHttpClient
对象,如下:
RxBaiduHttp.get("/article/list/0/json")
.asString()
.subscribe(s -> { //这里的s为String类型,即Http请求的返回结果
//成功回调
}, throwable -> {
//失败回调
});
@Converter
该注解可以为某个请求指定单独的Converter,用于数据解析,如下:
public class RxHttpManager {
@Converter(name = "FastJsonConverter")
public static IConverter fastJsonConverter = FastJsonConverter.create();
}
此时Rebuild一下项目,就会在RxHttp
类下生成setFastJsonConverter()
方法,发请求时,调用该方法,就会使用FastJsonConverter
解析数据,如下:
RxHttp.get("/article/list/0/json")
.setFastJsonConverter()
.asString()
.subscribe(s -> { //这里的s为String类型,即Http请求的返回结果
//成功回调
}, throwable -> {
//失败回调
});
到这,或许你猜到了,该注解也有className
字段,如下:
public class RxHttpManager {
@Converter(name = "FastJsonConverter",className = "FastJson")
public static IConverter fastJsonConverter = FastJsonConverter.create();
}
此时Rebuild一下项目,就是生成RxFastJsonHttp
类,通过该类发请求,就会默认使用FastJsonConverter
解析数据,如下:
RxFastJsonHttp.get("/article/list/0/json")
.asString()
.subscribe(s -> { //这里的s为String类型,即Http请求的返回结果
//成功回调
}, throwable -> {
//失败回调
});
Domain、OkClient、Converter注解的className字段
到这,我们知道,@Domain、@OkClient、@Converter
注解,都可以指定className
字段类生成对于的RxXxxHttp
类,通过该类发请求,就会默认使用我们指定的域名、OkHttpClient及Converter,那么,试想一下,如果我们这三个注解,指定的className
的名字都一样,会发生什么呢?如下:
public class RxHttpManager {
@Domain(name = "Google",className = "Simple")
public static String googleUrl = "https://www.google.com";
@OkClient(name = "BaiduClient",className = "Simple")
public static OkHttpClient baiduClient = new OkHttpClient.Builder().build();
@Converter(name = "FastJsonConverter",className = "Simple")
public static IConverter fastJsonConverter = FastJsonConverter.create();
}
以上,className
字段都取名为Simple
,此时只会生成一个RxSimpleHttp
类,该类默认使用的域名是googleUrl
;默认的OkHttpClient对象为baiduClient
;默认的Converter为FastJsonConverter
,此时,使用RxSimpleHttp
发请求,如下:
RxSimpleHttp.get("/article/list/0/json")
.asString()
.subscribe(s -> { //这里的s为String类型,即Http请求的返回结果
//成功回调
}, throwable -> {
//失败回调
});
//请求url:https://www.google.com/article/list/0/json
//使用BaiduClient执行请求
//使用FastJsonConverter解析数据
注:同一类型注解,className字段取名不能一样,否则编译不通过
@Parser
先来看看源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface Parser {
//指定名字后,就会在RxHttp下生成fromXXX方法
String name();
}
@Parser
标签作用于Parser
接口的实现类,指定名字后,Rebuild一下项目,就会在RxHttp下生成asXXX方法。
在RxHttp 一条链发送请求之强大的数据解析功能(二)一文中,我们也自定义了一个ResponseParser解析器,同时使用了@Parser(name = "Response")
注解,我们再次贴上源码
@Parser(name = "Response")
public class ResponseParser<T> extends AbstractParser<T> {
//省略内部代码
}
然后Rebuild 一下项目,RxHttp下就会自动生产一个public <T> Observable<T> asResponse(Class<T> type)
方法,如:
public class RxHttp {
private Param param;
private RxHttp(Param param) {
this.param = param;
}
//通过注解Parser生成的方法
public <T> Observable<T> asResponse(Class<T> type) {
return asParser(new ResponseParser<T>(type));
}
//省略了其它方法
}
此时我们就可以直接使用asResponse
方法去解析数据了。
String url = "https://www.wanandroid.com/article/list/0/json";
RxHttp.get(url)
.asResponse(User.class)
...省略部分代码
可见,代码更加的简洁了
注:@Parser
注解只能作用与Parser
的实现类,不能是接口和抽象类,且必须要提供两个构造方法,否则编译不通过
@Param
先来看看@Param
的源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface Param {
//指定在RxHttp类中生成的静态方法名
String methodName();
}
@Param
标签只能作用于AbstractPostParam
的实现类上,否则编译器会报错,指定方法名后,Rebuild一下项目,就会自动在RxHttp类下生成指定方法名的静态方法。
在RxHttp 一条链发送请求之强大的Param类(三)一文中,我们自定义了一个PostEncryptJsonParam
,并为它使用了注解标签@Param(methodName = "postEncryptJson")
我们再次贴上该类的源码
@Param(methodName = "postEncryptJson") //指定postEncryptJson为方法名
public class PostEncryptJsonParam extends AbstractPostParam {
//省略内部代码
}
然后Rebuild 一下项目,就可以看到在RxHttp下多了一个postEncryptJson
方法,并在方法内new 出了一个PostEncryptJsonParam
对象传给了RxHttp
public class RxHttp {
private Param param;
private RxHttp(Param param) {
this.param = param;
}
public static RxHttp with(Param param) {
return new RxHttp(param);
}
//通过注解Param生成的方法
public static RxHttp postEncryptJson(String url) {
return with(new PostEncryptJsonParam(url));
}
//省略了其它方法
}
接下来,我们就可以直接通过RxHttp发送PostEncryptJsonParam
请求
String url = "https://www.wanandroid.com/article/list/0/json";
RxHttp.postEncryptJson(url) //这里get,代表Get请求
.add("key", "value") //添加参数
//省略部分代码
可见@Param
标签,在一定程度上降低了耦合,使我们并不需要关注具体的实现,使用 RxHttp
类即可搞定任意请求
注:@Param
标签只能作用与Param
接口的实现类,该类不能是接口、抽象类,且必须提供一个public 且仅带一个url参数的构造方法,在编译时会做检查。
小结
最后,本文如果有写的不对的地方,请广大读者指出。 如果觉得我写的不错,记得给我点赞RxHttp
转载请注明出处,谢谢🙏。