zoukankan      html  css  js  c++  java
  • Retrofit添加自定义转换器

    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

  • 相关阅读:
    ubuntu的php7与apache2的环境搭建
    git服务器搭建post-receive 钩子部署服务端代码
    node redis安装与使用
    微信小程序坑集
    微信小程序登录
    mobx react
    react-native-router-flux 下部导航
    java
    java
    java
  • 原文地址:https://www.cnblogs.com/xl-phoenix/p/6854841.html
Copyright © 2011-2022 走看看