Retrofit2开始支持多种 Converter 并存,在之前,如果你遇到这种情况:一个 API 请求返回的结果需要通过 JSON 反序列化,另一个 API 请求需要通过 proto 反序列化,唯一的解决方案就是将两个接口分离开声明。

interface SomeProtoService {
@GET("/some/proto/endpoint")
Call<SomeProtoResponse> someProtoEndpoint();
} interface SomeJsonService {
@GET("/some/json/endpoint")
Call<SomeJsonResponse> someJsonEndpoint();

因为一个 REST adapter 只能绑定一个 Converter 对象。但是接口的声明是要语意化的。API 接口应该通过功能实现分组,比如: account 的接口,user 的接口,或者 Twitter 相关的接口。返回格式的差异不应该成为分组时候的阻碍。

现在,可以都放在一起了。

interface SomeService {
@GET("/some/proto/endpoint")
Call<SomeProtoResponse> someProtoEndpoint(); @GET("/some/json/endpoint")
Call<SomeJsonResponse> someJsonEndpoint();
}

第一个方法返回了一个 proto 对象。

SomeProtoResponse —> Proto? Yes!

原理很简单,其实就是对着每一个 converter 询问他们是否能够处理某种类型。我们问 proto 的 converter: “Hi, 你能处理 SomeProtoResponse 吗?”,然后它尽可能的去判断它是否可以处理这种类型。我们都知道:Protobuff 都是从一个名叫 message 或者 message lite 的类继承而来。所以,判断方法通常就是检查这个类是否继承自 message。

在面对 JSON 类型的时候,首先问 proto converter,proto converter 会发现这个不是继承子 Message 的,然后回复 no。紧接着移到下一个 JSON converter 上。JSON Converter 会回复说我可以!

SomeJsonResponse —> Proto? No! —> JSON? Yes!

因为 JSON 并没有什么继承上的约束。所以我们无法通过什么确切的条件来判断一个对象是否是 JSON 对象。以至于 JSON 的 converters 会对任何数据都回复说:我可以处理!这个一定要记住,** JSON converter 一定要放在最后,不然会和你的预期不符 **。

另一个要注意的是,现在已经不提供默认的 converter 了。如果不显性的声明一个可用的 Converter 的话,Retrofit 是会报错的:提醒你没有可用的 Converter。因为核心代码已经不依赖序列化相关的第三方库了,我们依然提供对 Converter 的支持,不过你需要自己引入这些依赖,同时显性的声明 Retrofit 需要用的 Converter 有哪些。

参考博客:用 Retrofit 2 简化 HTTP 请求

下面来看一个实际的例子

默认情况下,Retrofit 只能反序列化 HTTP 主体进入 OkHttp 的 ResponseBody 类型,它只能接受其 RequestBody 类型 @Body。

转换器可以被添加到支持其他类型。提供了方便适应流行的串行化库, Retrofit 提供了六兄弟模块如下:

  • Gson: com.squareup.retrofit:converter-gson
  • Jackson: com.squareup.retrofit:converter-jackson
  • Moshi: com.squareup.retrofit:converter-moshi
  • Protobuf: com.squareup.retrofit:converter-protobuf
  • Wire: com.squareup.retrofit:converter-wire
  • Simple XML: com.squareup.retrofit:converter-simplexml

Retrofit不支持开箱即用(如YAML,TXT,custom format)的API进行通信,所以我们定义一个TXT的转换器

public class ToStringConverterFactory extends Converter.Factory {
static final MediaType MEDIA_TYPE = MediaType.parse("text/plain"); @Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
if (String.class.equals(type)) {
return new Converter<ResponseBody, String>() {
@Override public String convert(ResponseBody value) throws IOException {
return value.string();
}
};
}
return null;
} @Override public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
if (String.class.equals(type)) {
return new Converter<String, RequestBody>() {
@Override public RequestBody convert(String value) throws IOException {
return RequestBody.create(MEDIA_TYPE, value);
}
};
}
return null;
}
}

在声明的时候

Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(new ToStringConverterFactory())
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(mBaseUrl)
.client(okHttpClient)
.build();

记住上面说过的, JSON 的 converters 会对任何数据都回复说:我可以处理!** JSON converter 一定要放在最后,不然会和你的预期不符 **。

这样便可以处理TXT格式的请求和应答了。

详细示例参考:square/retrofit

Retrofit添加自定义转换器的更多相关文章

  1. 「2020 新手必备 」极速入门 Retrofit + OkHttp 网络框架到实战,这一篇就够了!

    老生常谈 什么是 Retrofit ? Retrofit 早已不是什么新技术了,想必看到这篇博客的大家都早已熟知,这里就不啰嗦了,简单介绍下: Retrofit 是一个针对 Java 和 Androi ...

  2. Retrofit简介与使用方法(翻译)

    简介 Retrofit 是一个Square开发的类型安全的REST安卓客户端请求库.这个库为网络认证.API请求以及用OkHttp发送网络请求提供了强大的框架.Retrofit库让从web api下载 ...

  3. 自定义MessageConverter--消息转换器

    我们在进行发送消息的时候,正常情况下消息体为二进制的数据方式进行传输,如果希望内部帮我们进行转换,或者指定自定义的转换器,就需要用到MessageConverter 自定义常用转换器:MessageC ...

  4. Spring Boot 学习(2)

    文 by / 林本托 Tips 做一个终身学习的人. 源代码:github下的/code01/ch2. 配置 Web 应用程序 在上一章中,我们学习了如何创建一个基本的应用程序模板,并添加了一些基本功 ...

  5. Flask-论坛开发-1-基础知识

    对Flask感兴趣的,可以看下这个视频教程:http://study.163.com/course/courseLearn.htm?courseId=1004091002 1. 第一个 flask 程 ...

  6. [转]使用自定义HttpMessageConverter对返回内容进行加密

    今天上午技术群里的一个人问” 如何在 Spring MVC 中统一对返回的 Json 进行加密?”. 大部分人的第一反应是通过 Spring 拦截器(Interceptor)中的postHandler ...

  7. Retrofit--官网2.1.0

    Retrofit--官网2.1.0 android Retrofit 介绍 API 描述 请求方法 URL 处理 请求体 表单的 ENCODED 和 MULTIPART HEADER 处理 同步 VS ...

  8. HttpMessageConverter进行加密解密

    技术交流群: 233513714 使用自定义HttpMessageConverter对返回内容进行加密 今天上午技术群里的一个人问” 如何在 Spring MVC 中统一对返回的 Json 进行加密? ...

  9. Flask中获取参数(路径,查询,请求体,请求头)

    上一篇中已经讲述了:HTTP协议向服务器传参有几种途径{ 链接 } 在Flask中同样通过这4中传参途径进行归纳: 1. URL中路径参数的获取: 拓展: # 路由参数/路径参数:http://127 ...

随机推荐

  1. ALGO-140_蓝桥杯_算法训练_P1101

    有一份提货单,其数据项目有:商品名(MC).单价(DJ).数量(SL).定义一个结构体prut,其成员是上面的三项数据.在主函数中定义一个prut类型的结构体数组,输入每个元素的值,计算并输出提货单的 ...

  2. 解决MSDE安装回滚的问题

    rem 解决MSDE安装回滚的问题.bat rem 设置为手动rem sc config "LanmanServer" start= DEMAND rem 设置为自动sc conf ...

  3. SpringSecurity-ChannelProcessingFilter的作用

    ChannelProcessingFilter决定的是web请求的通道,即http或https. 在springsecurity配置文件中添加这样一行 <intercept-url patter ...

  4. gulp学习总结

    一.gulp使用-博客推荐: http://www.sheyilin.com/2016/02/gulp_introduce/ 二.gulp的作用 gulp是一个前端构建工具,它是一个工具框架,可以通过 ...

  5. java1.8新特性(三 关于 ::的用法)

    java1.8 推出了一种::的语法 用法 身边 基本没人用1.8的新API 目前 我也是只处于学习 运用 阶段 有点 知其然不知其所以然 通过后面的学习,及时查漏补缺 一个类中 有 静态方法 ,非静 ...

  6. jquery add() 和js add()

    HTML DOM add() 方法 HTML DOM Select 对象 定义和用法 add() 方法用于向 <select> 添加一个 <option> 元素. 语法 sel ...

  7. [转][PowerShell]ps执行重启IIS

    来自:https://www.aliyun.com/jiaocheng/871477.html write-output 'Restarting IIS servers ............... ...

  8. MySQL · 引擎特性 · 基于InnoDB的物理复制实现(转载)

    http://mysql.taobao.org/monthly/2016/05/01/ 在开始之前,你需要对InnoDB的事务系统有个基本的认识.如果您不了解,可以参考我之前的几篇关于InnoDB的文 ...

  9. HDOJ 2013 蟠桃记

    #include<iostream> using namespace std; int main() { int n; while (cin >> n) { ; ;i < ...

  10. centos7.0下增加swap分区大小

    承接上篇文章扩容磁盘空间后增加根分区的大小后,来扩容swap分区的空间 检查当前的swap分区情况 # free -m # free -g [root@localhost ~]# free -m to ...