-
-
Notifications
You must be signed in to change notification settings - Fork 458
高级功能
通过自定义Parser,我们可以非常方便的解析Response<T>
类型数据,并统一对code做判断,数据结构如下:
public class Response<T> {
private int code;
private String msg;
private T data;
//这里省略get、set方法
}
自定义ResponseParser代码如下:
@Parser(name = "Response", wrappers = {PageList.class})
public class ResponseParser<T> extends TypeParser<T> {
//该构造方法是必须的
protected ResponseParser() { super(); }
//如果依赖了RxJava,该构造方法也是必须的
public ResponseParser(Type type) { super(type); }
@Override
public T onParse(okhttp3.Response response) throws IOException {
//将okhttp3.Response转换为自定义的Response对象
Response<T> data = Converter.convertTo(response, Response.class, types); //这里的types就是自定义Response<T>里面的泛型类型
T t = data.getData(); //获取data字段
if (data.getCode() != 200 || t == null) {//这里假设code不等于200,代表数据不正确,抛出异常
throw new ParseException(String.valueOf(data.getCode()), data.getMsg(), response);
}
return t;
}
}
以上代码,需要注意两个地方
第一,我们在类开头使用了@Parser
注解,该注解有两个参数,如下:
-
name
代表解析器的名称,这里取名为Response
,于是在RxHttp
类下就会生成toObservableResponse(Class<T>)
、toObservableResponseList(Class<T>)
方法(命名方式为:toObservable +name
属性的值); 协程下会生成toAwaitResponse<T>、toFlowResponse<T>
方法。 -
wrappers
该参数是可选的,可以把他理解为泛型T
的包装类,需要传入Class[]
数组对象,这里我们传入了{PageList.class}
这个类,于是就会生成toObservableResponsePageList(Class<T>)
方法。(命名方式为:toObservable +name
属性的值+Class
类名); 该参数协程下无效,因为对于协程,toAwaitResponse<T>()
方法里面的T想写啥就可以写啥,如toAwaitResponse<List<T>>()、toAwaitResponse<PageList<T>>()
注:PageList类需要自己定义,用于加载分页数据,Demo里有这个类
第二,我们在if
语句里,对code做了判断,非200或者data为空时,就抛出异常,并带上了code及msg字段,所以我们在异常回调的地方就能拿到这两个字段
此时,我们就可以通过这3个方法,直接拿到T
、List<T>
、PageList<T>
类型数据,并且对code做了统一的判断,直接来看看如何使用这个解析器
//第一种方式,使用@parser注解生成的toObservableResponse方法
RxHttp.postForm("/service/...") //发送post表单请求
.add("key", "value") //添加参数,可调用多次
.toObservableResponse(Student.class) //返回Student类型
//.toObservableResponseList(Student.class) //返回List<Student>类型
//.toObservableResponsePageList(Student.class) //返回PageList<Student>类型
.subscribe(student -> {
//请求成功,这里能拿到 Student对象
}, throwable -> {
//请求失败
});
//kotlin环境下,也可以直接使用toObservableResponse<T>方法,更加简单如下:
RxHttp.postForm("/service/...") //发送post表单请求
.add("key", "value") //添加参数,可调用多次
.toObservableResponse<Student>() //返回Student类型
//.toObservableResponse<List<Student>>() //返回List<Student>类型
//.toObservableResponse<PageList<Student>>() //返回PageList<Student>类型
.subscribe({
//请求成功,这里能拿到 Student对象
}, {
//请求失败
});
//第二种方式,直接使用toObservable(Parser<T>)方法
RxHttp.postForm("/service/...") //发送post表单请求
.add("key", "value") //添加参数,可调用多次
.toObservable(new ResponseParser<Student>(){}) //返回Student类型
.subscribe(student -> {
//请求成功,这里能拿到 Student对象
}, throwable -> {
//请求失败
});
以上两种方式,除了写法上的区别,其它都一样,相信大家都会选择第一种方式,不仅写法简单,还降低了耦合。
自定义Param,想较于自定义Parser,要更加的简单,我们只需根据自己的需求,继承NoBodyParam、FormParam、JsonParam等,增加或者重写方法即可,比如我们有以下3种情况,需要自定义Param,如下:
- postForm请求,需要将所有添加的参数,拼接在一起,随后加密,最后将加密的字符串添加到请求头中
- postJson请求,需要将所有的参数,也就是json字符串加密后再发送出去
- FormParam里面的API不够用,我要自定义API
这种情况,我们需要继承FormParam,并重写getRequestBody()方法,如下:
@Param(methodName = "postEncryptForm")
public class PostEncryptFormParam extends FormParam {
public PostEncryptFormParam(String url) {
super(url, Method.POST); //Method.POST代表post请求
}
@Override
public RequestBody getRequestBody() {
//获取到所有通过add系列方法添加的参数
List<KeyValuePair> bodyParam = getBodyParam();
//获取到所有通过addQuery系列方法添加的参数
List<KeyValuePair> queryParam = getQueryParam();
String encryptStr = "加密后的字符串"; //根据上面拿到的参数,自行实现加密逻辑
addHeader("encryptStr", encryptStr);
return super.getRequestBody();
}
}
这种情况,我们需要继承JsonParam,也重写getRequestBody()方法,如下:
@Param(methodName = "postEncryptJson")
public class PostEncryptJsonParam extends JsonParam {
public PostEncryptFormParam(String url) {
super(url, Method.POST);
}
@Override
public RequestBody getRequestBody() {
//获取到所有通过add系列方法添加的参数
Map<String, Object> bodyParam = getBodyParam();
//获取到所有通过addQuery系列方法添加的参数
List<KeyValuePair> queryParam = getQueryParam();
String encryptStr = "加密后的字符串"; //根据上面拿到的参数,自行实现解密逻辑
return RequestBody.create(MEDIA_TYPE_JSON, encryptStr); //发送加密后的字符串
}
}
我们继承FormParam,并新增两个test方法`,如下:
@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;
}
}
同样的问题,我们怎么用这3个自定义的Param呢?我想大多数人在类名前发现类@Param
注解,并为Param取了别名。那这个又有什么作用呢?
答案揭晓,只要在自定的Param上使用了@Param
注解,并取了别名,就会在RxHttp类自动生成一个跟别名一样的方法,在上面我们自定义了3个Param,并分别取别名为postEncryptForm、postEncryptJson、postTestForm,此时就会在RxHttp类中生成postEncryptForm(String)
、postEncryptJsonString)
、postTestForm(String)
这3个方法,我们在RxHttp这个类中来看下:
public static RxHttpPostEncryptFormParam postEncryptForm(String url, Object... formatArgs) {
return new RxHttpPostEncryptFormParam(new PostEncryptFormParam(format(url, formatArgs)));
}
public static RxHttpPostEncryptJsonParam postEncryptJson(String url, Object... formatArgs) {
return new RxHttpPostEncryptJsonParam(new PostEncryptJsonParam(format(url, formatArgs)));
}
public static RxHttpPostTestFormParam postTestForm(String url, Object... formatArgs) {
return new RxHttpPostTestFormParam(new PostTestFormParam(format(url, formatArgs)));
}
发请求时,只需要调用对应的方法就好,如:
//发送加密的postForm请求
RxHttp.postEncryptForm("/service/...")
.add("key", "value") //添加参数,可调用多次
.toObservableString() //返回Observable<String>类型
.subscribe(s-> {
//请求成功
}, throwable -> {
//请求失败
});
//发送加密的postJson请求
RxHttp.postEncryptJson("/service/...")
.add("key", "value") //添加参数,可调用多次
.toObservableString() //返回Observable<String>类型
.subscribe(s-> {
//请求成功
}, throwable -> {
//请求失败
});
那我自定义的API如何调用呢,so easy!!!!,选择对应的请求方法后,就可以直接调用,如下:
//发送加密的postJson请求
RxHttp.postTestJson("/service/...")
.test(100L, 99.99F) //调用自定义的API
.test1("testKey", 88.88D) //调用自定义的API
.add("key", "value") //添加参数,可调用多次
.toObservableString() //返回Observable<String>类型
.subscribe(s-> {
//请求成功
}, throwable -> {
//请求失败
});
RxHttp内部默认使用来GsonConverter,并且额外提供了6个Converter,如下:
//非必须,根据自己需求选择 RxHttp默认内置了GsonConverter
implementation "com.github.liujingxing.rxhttp:converter-serialization:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-fastjson:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-jackson:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-moshi:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-protobuf:$rxhttp_version"
implementation "com.github.liujingxing.rxhttp:converter-simplexml:$rxhttp_version"
即使这样,RxHttp也无法保证满足所有的业务需求,为此,我们可以选择自定义Converter,自定义Converter需要继承IConverter接口,如下:
public class TestConverter implements IConverter {
/**
* 请求成功后会被回调
* @param body ResponseBody
* @param type 泛型类型
* @param onResultDecoder 是否需要对结果进行解码/解密
*/
@Override
public <T> T convert(ResponseBody body, Type type, boolean onResultDecoder) throws IOException {
//自行实现相关逻辑
return null;
}
/**
* json请求前会被回调,需要自行根据泛型T创建RequestBody对象,并返回
*/
@Override
public <T> RequestBody convert(T value) throws IOException {
//自行实现相关逻辑
return null;
}
}
以上两个convert方法根据自身业务需求自行实现,可以参考RxHttp提供FastJsonConverter、SimpleXmlConverter等Converter
请查看设置Converter