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. 我的less学习之路

    less注释 可以在代码中使用块样式(/* */)和行内注释(//),但是当编译LESS代码时,单行注释不会显示在CSS文件中.开发中主要维护的是less文件,所以可以使用行内注释,最终编译的css文 ...

  2. nginx - 性能优化,突破十万并发

    一般来说nginx配置文件中对优化比较有作用的为以下几项: worker_processes 8; nginx进程数,建议按照cpu数目来指定,一般为它的倍数. worker_cpu_affinity ...

  3. ghost之后仍然中病毒----与病毒的斗争

    ghost之后仍然中病毒----与病毒的斗争我的电脑系统是XP,从来都没有安装任何杀毒软件,所有的软件都是安装在C盘的,感觉系统卡顿就用Windows一键还原(基于DOS下的ghost)还原一下,一直 ...

  4. 我的第一个react native

    虽然react native出来了很久,但是自己一直因为各种原因没有接触学习,中间尝试过一次,但是因为复杂的环境配置而放弃了.现在,终于因为公司的项目不得不去学习了,当然了,再配置开发环境上面,我还是 ...

  5. mysql默认8小时连接断开机制解决

    转载连接:http://www.myexception.cn/database/1639209.html 本文提供了对c3p0与DBCP连接池连接MySql数据库时, 8小时内无请求自动断开连接的解决 ...

  6. Vue.js系列之项目结构说明

    转:https://www.jb51.net/article/111658.htm 前言 在上一篇项目搭建文章中,我们已经下载安装了node环境以及vue-cli,并且已经成功构建了一个vue-cli ...

  7. Jmeter(二十七)Jmeter Question 之“集成Ant+Jenkins自动化”

    首先介绍一下Ant.Apache Ant,是一个将软件编译.测试.部署等步骤联系在一起加以自动化的一个工具,大多用于Java环境中的软件开发.由Apache软件基金会所提供. 是的.还是Apache家 ...

  8. echarts饼图配置

    js引用和配置div <div id="container" style="height: 100%"></div> <scrip ...

  9. docker设置容器固定ip

    docker安装后,默认会创建三种网络类型,bridge.host和none,可通过如下命令查看 sudo docker network ls 1 bridge:网络桥接 默认情况下启动.创建容器都是 ...

  10. jstat 详解

    最近项目里面使用到了多线程,有时候多线程会存在挂掉的情况,趁机好好学习总结一下JVM调优的方法. jstat使用: #jstat -help|-options #jstat -<option&g ...