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. CAD中的各种Polyline

    序号 类 类名 dxf代码 1 Polyline2d AcDb2dPolyline POLYLINE 2 Polyline3d AcDb3dPolyline POLYLINE 3 Polyline A ...

  2. 关于linux中的system函数

    Linux下使用system()函数一定要谨慎 https://blog.csdn.net/senen_wakk/article/details/51496322 system()正确应用 https ...

  3. python中numpy的random模块

    1. rand(d0,d1,.....,dn)产生[0,1]的浮点随机数,括号里面的参数可以指定产生数组的形状    例如:np.random.rand(3,2)则产生 3×2的数组,里面的数是0-1 ...

  4. gcc编译工具生成动态库和静态库之一----介绍

     1.库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. ...

  5. .NET数据请求序列化

    这是一个.ner框架中经常用到的数据映射类,此类主要承接业务应用做数据的增删查改操作.通过序列化将查询数据映射为需要的类. 由于经常会用到,这里收藏一下. data用作SQL数据库链接操作: Repo ...

  6. PAT 甲级 1011 World Cup Betting (20)(20 分)

    1011 World Cup Betting (20)(20 分)提问 With the 2010 FIFA World Cup running, football fans the world ov ...

  7. PAT 乙级 1066 图像过滤(15) C++版

    1066. 图像过滤(15) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 图像过滤是把图像中不重要的像素都染成 ...

  8. jQuery的html和css

    jQuery每次返回的都是当前的集合对象: 每个方法用的时候都会把他的元素对象返回,他每次返回的都是最近的那个元素: 1.addclass() 备选元素添加一个类名 2.removeclass() 移 ...

  9. C++ Programming Language中的Calculator源代码

    C++ Programming Language 4th中的Calculator源代码整理,因为在C++ Programming Language中,涉及了很多文件位置之类的变化,所以,这里只是其中的 ...

  10. etcd安装和所遇到的坑

    首先参照 https://www.cnblogs.com/lyzw/p/6016789.html来安装 虚拟机:VMware® Workstation 12 Pro 系统:CentOS Linux r ...