Retrofit接入RxJava2的使用以及XML在Retrofit中的使用
2017-09-15 10:00
267 查看
在之前的博客里,采用了RxJava 1.1.10 和 Retrofit 2.1.0来搭建网络框架。在这片博客里,我们将采用RxJava2.x的版本来接入Retrofit进行搭建。由于RxJava2.x和RxJava1.x的版本差异性,所以这里我们把重点放在RxJava2的使用上。
项目地址:NetFrameWork。该项目中包含两个module,rxjava2和xmlformat,xmlformat是在rxjava2上做的改版,将JSON的传输格式改成XML传输格式的网络框架。而这套网络框架又是基于第一版RxRetrofitFramework的思想: Retrofit+RxJava的使用 。
RxJava 1 的订阅者是Subscriber,提供了onStart、onNext、onError、onCompleted四个方法,当需要取消订阅功能时,由Subscriber进行unsubscribe操作。
RxJava 2 的订阅者是Observer,提供了onSubscribe、onNext、onError、onComplete四个方法,当需要取消订阅功能时,由Observer的onSubscribe传递过来的对象Disposable 进行dispose操作。
对重试策略的修订:
RxJava 1 和RxJava 2 的重试策略的操作符都是retryWhen,但由于改版,因此这里对触发onError之后的操作进行了变更,通过flatMap分发Exception,并判断该错误类型是否需要发送给订阅者错误信息或者进行返回数据源。
在整个项目中,RxJava1 和RxJava2的应用最大的不同,就在于类
先来借鉴JSON项目的模式,我们最常见的是将具体的数据封装在一个统一的协议中进行响应。比如这样:
因此我们才能在我们的设计框架中通过外层Bean的封装:
然而,对于同样有着协议外壳XML的传输方式,在解析的时候,我们一般都是亲自采用SAX、DOM等等解析的方式,非常不方便代码的节省和统一的管理。因此,这里我们想到了
和
但内层数据的获取,还得我们编写响应的代码去解析。但我们这里发现,
因此,我们需要做的事情是:
1. 新建一个
2. 将网络请求的返回类型由通用的外层协议直接改为
3. 新建响应Bean的model,继承协议类型,将data数据指向Bean并加上响应的注解,添加方法请求网络。,或者不存在统一的外层协议时,直接继承Bean,添加网络请求,见
4. 在执行请求后,通过工具进行解析。
于是,我们可以通过上述方案得到对应的解析对象了。
以上我们完成了响应,接下来该完成请求对象的封装,比如说,我们向服务器提交一个POST的BODY请求,如何转换为XML,其实很简单,利用
但是这个工具要求提供参数Request,但我们并没有方式直接构建一个Request,因此,这里我们剩下最省事的办法就是利用Retrofit提供的接口添加一个
因为类的包保护机制,所以我们可以复制
这里唯一的不同就在于
如果有任何疑问,欢迎留言讨论。
项目地址:NetFrameWork。该项目中包含两个module,rxjava2和xmlformat,xmlformat是在rxjava2上做的改版,将JSON的传输格式改成XML传输格式的网络框架。而这套网络框架又是基于第一版RxRetrofitFramework的思想: Retrofit+RxJava的使用 。
版本更新内容:
对订阅者的改动:RxJava 1 的订阅者是Subscriber,提供了onStart、onNext、onError、onCompleted四个方法,当需要取消订阅功能时,由Subscriber进行unsubscribe操作。
mSubscriber = new Subscriber<BaseServiceResult<T>>() { @Override public void onStart() { super.onStart(); } @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(BaseServiceResult<T> t) { // mCallback.doSomething } };
RxJava 2 的订阅者是Observer,提供了onSubscribe、onNext、onError、onComplete四个方法,当需要取消订阅功能时,由Observer的onSubscribe传递过来的对象Disposable 进行dispose操作。
mSubscriber = new Observer<NetServiceResult<T>>() { @Override public void onSubscribe(Disposable d) { mDisposable = d; } @Override public void onNext(NetServiceResult<T> t) { // mCallback.doSomething } @Override public void onError(Throwable e) { } @Override public void onComplete() { } };
对重试策略的修订:
RxJava 1 和RxJava 2 的重试策略的操作符都是retryWhen,但由于改版,因此这里对触发onError之后的操作进行了变更,通过flatMap分发Exception,并判断该错误类型是否需要发送给订阅者错误信息或者进行返回数据源。
retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() { @Override public ObservableSource<?> apply(@NonNull Observable<Throwable> throwableObservable) throws Exception { return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() { @Override public ObservableSource<?> apply(@NonNull Throwable throwable) throws Exception { if (mNeedRetry && throwable instanceof IOException) { mNeedRetry = false; return Observable.timer(retryDelayMillis, TimeUnit.MILLISECONDS); } // For anything else, don't retry return Observable.error(throwable); } }); } })
在整个项目中,RxJava1 和RxJava2的应用最大的不同,就在于类
NetProcessor的升级。这个类也是对外接口暴露的核心内容,在设计思想上是一个由外部可以直接采用链式模式来对网络请求过程进行多元化处理,如取消请求、缓存回调、错误重试,甚至于还可以基于此进行项目自定制,如参数加密、排序处理,网络验证等等的一个工具。
XML格式传输
通常来讲,数据的网络传输格式一般都是JSON、XML,但JSON在应用中更为多见,JSON解析封装的工具更是非常之多。但不可否认的也有XML格式的需求,这里我们就讲如何封装XML请求和解析XML响应。先来借鉴JSON项目的模式,我们最常见的是将具体的数据封装在一个统一的协议中进行响应。比如这样:
{ "code" : 0, "msg" : "success", "data" : { ... } }
因此我们才能在我们的设计框架中通过外层Bean的封装:
BaseServiceResult<T>,传入内层数据的class和泛型,利用JSON解析工具获取解析类型并回调回传。
然而,对于同样有着协议外壳XML的传输方式,在解析的时候,我们一般都是亲自采用SAX、DOM等等解析的方式,非常不方便代码的节省和统一的管理。因此,这里我们想到了
SimpleXMLConvertFactory这个工具。
和
JSONConvertFactory的使用方式和目的一致,都是用来解析数据的,但不同的地方就是,
SimpleXMLConvertFactory这个工具对Bean采用了注解的方式,而Retrofit的网络请求接口
NetServer在解析时,并不允许我们直接使用泛型T来获取响应内容,要么采用类似于
NetServiceResult<T>这种的解析方式。先解析外层协议,再解析内层数据。
但内层数据的获取,还得我们编写响应的代码去解析。但我们这里发现,
SimpleXMLConvertFactory工具中提供了类
SimpleXmlResponseBodyConverter的
convert(ResponseBody value)方法,可以直接解析响应内容。
@Override public T convert(ResponseBody value) throws IOException { try { T read = serializer.read(cls, value.charStream(), strict); if (read == null) { throw new IllegalStateException("Could not deserialize body as " + cls); } return read; } catch (RuntimeException | IOException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } finally { value.close(); } }
因此,我们需要做的事情是:
1. 新建一个
XmlResponseConverter工具,用来解析
ResponseBody。
2. 将网络请求的返回类型由通用的外层协议直接改为
ResponseBody。
3. 新建响应Bean的model,继承协议类型,将data数据指向Bean并加上响应的注解,添加方法请求网络。,或者不存在统一的外层协议时,直接继承Bean,添加网络请求,见
IPModel。
4. 在执行请求后,通过工具进行解析。
于是,我们可以通过上述方案得到对应的解析对象了。
以上我们完成了响应,接下来该完成请求对象的封装,比如说,我们向服务器提交一个POST的BODY请求,如何转换为XML,其实很简单,利用
SimpleXMLConvertFactory就可以达到。也就是说,有
XmlResponseConverter工具来解析响应,就有
XmlRequestConverter来封装请求。
但是这个工具要求提供参数Request,但我们并没有方式直接构建一个Request,因此,这里我们剩下最省事的办法就是利用Retrofit提供的接口添加一个
ConvertFactory,利用这个转换器来达到目的。因此我们就要构建自己的转换器,一是要能够封装请求参数,二是要屏蔽响应解析。
因为类的包保护机制,所以我们可以复制
SimpleXMLConvertFactory代码并做相应的改动。
public class XMLConvertFactory extends Converter.Factory { public static XMLConvertFactory create() { return create(new Persister()); } /** Create an instance using {@code serializer} for conversion. */ public static XMLConvertFactory create(Serializer serializer) { return new XMLConvertFactory(serializer, true); } /** Create an instance using a default {@link Persister} instance for non-strict conversion. */ public static XMLConvertFactory createNonStrict() { return createNonStrict(new Persister()); } /** Create an instance using {@code serializer} for non-strict conversion. */ @SuppressWarnings("ConstantConditions") // Guarding public API nullability. public static XMLConvertFactory createNonStrict(Serializer serializer) { if (serializer == null) throw new NullPointerException("serializer == null"); return new XMLConvertFactory(serializer, false); } private final Serializer serializer; private final boolean strict; private XMLConvertFactory(Serializer serializer, boolean strict) { this.serializer = serializer; this.strict = strict; } public boolean isStrict() { return strict; } @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { // 屏蔽响应解析 return null; } @Override public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { if (!(type instanceof Class)) { return null; } // 创建请求封装 return new XmlRequestBodyConverter<>(serializer); } }
final class XmlRequestBodyConverter<T> implements Converter<T, RequestBody> { private static final MediaType MEDIA_TYPE = MediaType.parse("application/xml; charset=UTF-8"); private static final String CHARSET = "UTF-8"; private final Serializer serializer; XmlRequestBodyConverter(Serializer serializer) { this.serializer = serializer; } @Override public RequestBody convert(T value) throws IOException { Buffer buffer = new Buffer(); try { OutputStreamWriter osw = new OutputStreamWriter(buffer.outputStream(), CHARSET); serializer.write(value, osw); osw.flush(); } catch (Exception e) { throw new RuntimeException(e); } return RequestBody.create(MEDIA_TYPE, buffer.readByteString()); } }
这里唯一的不同就在于
XMLConvertFactory对于
responseBodyConverter的处理,这里返回null表示不进行任何处理。至此,我们就完成了XML在Retrofit的使用。
如果有任何疑问,欢迎留言讨论。
相关文章推荐
- 在XML里的XSD和DTD以及standalone的使用2----具体使用详解
- java.lang.StringBuilder的使用以及如何post方式post xml
- (六)Webxml文件中添加taglib以及在页面中使用标签
- android: 静态XML和动态加载XML混合使用,以及重写Layout控件
- XML学习笔记(四):xml解析详解以及使用 DOM和SAX 解析XML :
- Java乔晓松-使用SAX,DOM,pull解析XML文件以及pull解析生成xml文件
- 微软BI 之SSIS 系列 - 在 SSIS 中使用 Web Service 以及 XML 解析
- Spring-property文件配置方法以及如何与工程分离~xml使用${}
- ACCU天气API以及Okhttp、Retrofit、RxJava的使用
- android: 静态XML和动态加载XML混合使用,以及重写Layout控件
- SS7.1_Hibernate_CRUD_ByXML~SS7.2_Hibernate_CRUD_ByXML使用Session对数据库进行增删改查以及saveOrUpdate/merge()的区别
- Retrofit2+RxJava2 使用POST方式提交JSON数据,服务器无法解析的问题
- 【SSH网上商城项目实战02】基本增删查改、Service和Action的抽取以及使用注解替换xml
- 【SSH网上商城项目实战02】基本增删查改、Service和Action的抽取以及使用注解替换xml
- 防火墙与路由器的区别以及何时直接使用防火墙接入外网
- javaweb学习总结十三(dom4j方式对XML文档进行解析以及Xpath的使用)
- spring中声明式事务管理控制介绍以及使用XML方式实现
- 使用MVP框架,retrofit结合Rxjava以及fresco加载图片,用recycleview实现
- XML的SelectNodes使用方法以及XPath
- XSD(XML Schema Definition)用法实例介绍以及C#使用xsd文件验证XML格式