前言
"后端更新换代, 新接口返回全用新的规则, 老接口不变!"...WTF!
"我们的这几个网站, 要做一个统一的 App, 后端都是现成的, 这是 API 文档."... 几个网站的 API 规范和请求 Host 地址居然完全不一样?...WTF!
... 千万只草泥马呼啸而过... 实时切换 BaseUrl?Retrofit 注解全加上 @Url?... 无奈...
虽然说现在已经有很多 Http 请求框架了, 也有很多针对 RxJava+Retrofit 的二次封装, 但是大多没有针对上述特殊情况下的处理方案. 因此, RxRetroHttp 应运而生.
GitHub 地址: https://github.com/BakerJQ/RxRetroHttp
总览
我们先来看看, RxRetroHttp 是通过什么方式处理这种情况的.
初始化
首先, 大多库的必备阶段: 初始化. 我们先来看看初始化的代码, 在 Application 的 onCreate 中执行
- RxRetroHttp.init(this)
- .setBaseUrl("http://api1.com/")
- .setApiResultClass(Api1Result.class)
- .generateRetroClient()
这样, 初始化就做完了... 此处应有掌声...
"我掌你大爷!!! 说好的处理多套 API 规则呢!!!"
额咳... 客观莫急... 待我徐徐道来
通过刚刚的初始化, 你已经设置了 App 中主 API 请求的基本配置. 如果你的 App 中, 就像前言里描述的那样, 需要对接多套 API 规则, 那么在初始化之后, 再加入如下代码
- RxRetroHttp.getInstance()
- .setBaseUrl("https://api2.com/")
- .setApiResultClass(Api2Result.class)
- .generateRetroClient("API2")
相信大家已经看出区别了吧, 没错, 就是在 generateRetroClient 这个方法中, 加入了一个 Tag, 而这个 Tag, 就是处理多套 API 请求的关键.
在 setApiResultClass 方法中, 传入的就是对于 API 规范的基类, 具体情况会在后面讲到.
调用
初始化完成后, 如何调用呢, 请看代码
RxRetroHttp.create(Api2Service.class, "API2").getApi2Info()
我们可以看到, 这就是 Retrofit 风格的调用方式, 而不同的, 就是增加了一个 Tag, 而这个 Tag, 就是在初始化阶段设置的 Tag, 当然, 对于主 API 来说, Tag 是不需要的.
在这里, Api2Service 也就是 Retrofit 风格的 ApiService, 但是也略有不同
- public interface Api2Service {
- @GET("test/info")
- Observable<Api2Info> getApi2Info();
- }
我们看看不同在哪, 下面是纯 Retrofit 的书写方式
- public interface Api2Service {
- @GET("test/info")
- Observable<Api2Result<Api2Info>> getApi2Info();
- }
没错, 区别就在于, 省去了基类的这一层包裹. 这么做的原因是, 个人认为, 在 ApiService 这一层, 不应该出现用于区分各套 API 规则的相关代码.
当然, 如果你还是希望以基类包裹的方式, 也是可以的, 那就是在初始化的时候, 不调用 setApiResultClass 方法就行了.
ApiResult
现在, 我们来看看 ApiResult.
在 setApiResultClass 方法中传入的, 是实现了 IApiResult 接口的请求返回基类, 简单的样例代码如下
- public class Api2Result<T> implements IApiResult<T> {
- private int code;
- private String msg;
- private T result;
- @Override
- public boolean isSuccess(){
- return code == 1;
- }
- @Override
- public T getData(){
- return result;
- }
- @Override
- public String getResultMsg(){
- return msg;
- }
- @Override
- public String getResultCode(){
- return String.valueOf(code);
- }
- @Override
- public String getDataField(){
- return "result";
- }
- }
其对应的返回 JSON 如下
- {
- code: 1,
- msg: "请求成功",
- result: {
- ...
- }
- }
这是一个较为常用的 API 返回格式, 而我们所要做的, 就是实现几个基本方法, 其中, isSuccess() 返回的是请求成功的判断, getData() 返回的是请求到的具体数据, getResultMsg() 返回的是 API 请求信息, getResultCode() 表示返回码, getDataField() 返回的是 JSON 数据中表示具体数据的字段 (在上面的 JSON 例子中, 就是 "result").
更多配置
Http 请求不可能没有相关的配置, 而本框架并没有为大家内置很多配置方法, 原因是, 我认为这并不是本框架的主要功能. 当然, 大家也是可以进行自定义配置的, 配置方式如下:
- RxRetroHttp.init(this).setXXX().setXXX();
- Retrofit.Builder retrofitBuilder = RxRetroHttp.getRetrofitBuilder();
- retrofitBuilder.setXXX().setXXX();
- OkHttpClient.Builder okHttpBuilder = RxRetroHttp.getOkHttpClientBuilder();
- okHttpBuilder.setXXX().setXXX();
- RxRetroHttp.getInstance().generateRetroClient();
- //RxRetroHttp.getInstance().generateRetroClient("YourTag")
当然各套 API 请求之间的配置也是隔离的. 框架也提供了一些简单的快捷配置方法, 比如 addInterceptor,addNetworkInterceptor 等, 更多的配置可以通过上述方式, 获取 retrofitBuilder 和 okHttpBuilder 来配置.
总结
通过 Tag 的方式或许不是最好的方式, 我也会继续尝试注解等其他的方式, 以对比便利性, 如果大家有更好的方案提议, 也希望能够通过提 issuer 的方式告诉我, 感谢大家.
更具体的使用方式, 欢迎来 GitHub 仓库里的 Demo 查看, 也欢迎和感谢各位 Star 支持.
再次贴一下 GitHub 地址: https://github.com/BakerJQ/RxRetroHttp
来源: https://juejin.im/post/5c43227fe51d4518c15507d4