Retrofit自定义请求转换器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Retrofit自定义请求转换器相关的知识,希望对你有一定的参考价值。

参考技术A 写之前不得提下接口,接口的设计是这样的

简单说下,接口请求是 application/json; ,每个请求参数里面包含一个通用的 header 里面有一些 api 、设备和 token 信息,通常这部分是定义到 Http 请求头 header 里面的,可能我们的接口比较任性...

在 header 里面我们写一个 OkHttp 拦截器 然后加 header 就可以了,请求体里面拦截器就无能为力了。所以我们用到了请求转换器。

我们在 Retrofit 的 ApiService 把 参数类 req 定义为 body ,通过自定义转换器给 body 加上 header 组装成 包含 header 和 body 的完整对象 param 。
以一个登录接口为例,说明下。
定义在 ApiService 的方法

调用,可以看到,我们的参数 UserLoginSearchDto 并没有定义 header 信息。这时自定义转换器就上场了。Retrofit 的代理实现类会通过请求转化器会把我们在 ApiService 定义的 @Body UserLoginSearchDto dto 序列化为 json 。

别忘了注册自定义转换器 RequestConvertFactory.create

Retrofit--官网2.1.0

Retrofit--官网2.1.0

 

 

介绍


RetrofitHTTP API 转换为 Java 的接口:

  1. public interface GitHubService
  2. @GET("users/{user}/repos"
  3. Call<List<Repo>> listRepos(@Path("user") String user); 

使用 Retrofit 类生成 GitHubService 的实例:

  1. Retrofit retrofit = new Retrofit.Builder() 
  2. .baseUrl("https://api.github.com/"
  3. .build(); 
  4.  
  5. GitHubService service = retrofit.create(GitHubService.class); 

GitHubService 实例上的每次调用都会产生一个到远程服务的同步、或异步的 HTTP 的请求:

  1. Call<List<Repo>> repos = service.listRepos("octocat"); 

使用注解描述 HTTP 请求:

  • 支持 URL 参数的占位符,支持请求参数

  • 对象和 response body 的转换(例如:JSON 等)

  • Multipart 请求体和文件上传

API 描述


接口方法和参数上的注解标识了如何处理一个请求。

请求方法


每个方法必须使用一个注解来提供请求类型和相对 URL 地址。请求类型注解一共有五个:GETPOSTPUTDELETEHEAD。注解中也可以指定相对的 URL 地址:

  1. @GET("users/list"

URL 中,也可以指定查询参数:

  1. @GET("users/list?sort=desc"

URL 处理


请求的 URL 中,可以使用占位符块和方法中的参数,对 URL 进行动态的更新。一个占位符块就是在 {} 之间包含的数字和字母。必须使用同样的数字和字母,使用 @Path 注解来申明相应的参数:

  1. @GET("group/{id}/users"
  2. Call<List<User>> groupList(@Path("id") int groupId); 

当然,也可以添加查询参数:

  1. @GET("group/{id}/users"
  2. Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort); 

复杂的查询参数(例如 Map 类型)的示例:

  1. @GET("group/{id}/users"
  2. Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options); 

请求体


可以使用 @Body 注解来把一个对象指定为 HTTPBODY

  1. @GET("group/{id}/users"
  2. Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options); 

也可以通过给 Retrofit 的实例指定转换器的方式对对象进行转换。如果没有添加转换器,仅能使用 RequestBody

表单的 ENCODED 和 MULTIPART


也可以申明方法来发送 form-encodedmultipart 的数据。

当方法上存在 @FormUrlEncoded 注解时,就会发送 form-encoded 的数据。@Filed 包含了键值对的键名称,后面的对象提供了键值对的值:

  1. @FormUrlEncoded 
  2. @POST("user/edit"
  3. Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last)

当方法上存在 @Multipart 注解时,就会发送 multipart 的数据,各部分使用 @Part 注解进行申明:

  1. @Multipart 
  2. @PUT("user/photo"
  3. Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description)

multipart 的各部分要么使用 Retrofit 的转换器,要么实现 RequestBody,用这样的方式来实现各自的序列化。

HEADER 处理


可以使用 @Headers 注解来为某个方法设置静态的头:

  1. @Headers("Cache-Control: max-age=640000"
  2. @GET("widget/list"
  3. Call<List<Widget>> widgetList(); 

 

  1. @Headers({ 
  2. "Accept: application/vnd.github.v3.full+json"
  3. "User-Agent: Retrofit-Sample-App" 
  4. }) 
  5. @GET("users/{username}"
  6. Call<User> getUser(@Path("username") String username)

注意:header中的各个部分不能相互覆盖。所有相同名称的header都会被包含在请求中。

也可以使用 @Header 注解对头部内容进行动态的更新。对应的参数必须由 @Header 进行提供。如果值为 null,那么将被忽略。如果不为 null,值将会使用 toString() 方法,最终使用 toString() 方法返回的值:

  1. @GET("user"
  2. Call<User> getUser(@Header("Authorization") String authorization) 

如果要给每个请求都添加头部,那么,可以使用 OkHttp interceptor 进行指定。

同步 VS 异步


Call 对象的实例上,即可以使用同步,也可以使用异步。它的每个实例只能使用一次,使用 clone() 方法就可以创建一个新的实例来使用。

Android 中,回调方法会在主线程中执行。在 JVM 中,回调将和执行 HTTP 请求发生在同一线程。

Retrofit 配置


默认地,Retrofit 有健全的默认值,但是,也可以自定义配置。

转换器


默认地,Retrofit 只会把 HTTP body 的内容反序列化到 OKHttpResponseBody 类型中,并且它只接收用 @Body 标注的 RequestBody 类型。

要支持其它的类型,可以添加转换器。为了方便起见,为了适配一些流行的序列化库,Retrofit 已经提供了六个模块:

  • Gson: com.squareup.retrofit2:converter-gson

  • Jackson: com.squareup.retrofit2:converter-jackson

  • Moshi: com.squareup.retrofit2:converter-moshi

  • Protobuf: com.squareup.retrofit2:converter-protobuf

  • Wire: com.squareup.retrofit2:converter-wire

  • Simple XML: com.squareup.retrofit2:converter-simplexml

  • Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

下面的示例中,使用 GsonConverterFactory 类来生成 GitHubService 的实现,该实现使用 Gson 作为反序列化的工具:

  1. Retrofit retrofit = new Retrofit.Builder() 
  2. .baseUrl("https://api.github.com"
  3. .addConverterFactory(GsonConverterFactory.create()) 
  4. .build(); 
  5.  
  6. GitHubService service = retrofit.create(GitHubService.class); 

自定义转换器


如果你需要与之通信的 API 使用了 Retrofit 不支持的内容格式(例如:YAML,文本,自定义格式等),或者你想使用一个其它的库来实现一个已经存在的格式,那么,就需要创建自己的转换器,这是一件非常简单的事情。创建一个类继承 Converter.Factory 类,然后,在构建适配器时,把它传给实例就可以了。

下载

2.1.0版本官方下载

使用 maven


  1. <dependency> 
  2. <groupId>com.squareup.retrofit2</groupId> 
  3. <artifactId>retrofit</artifactId> 
  4. <version>2.1.0</version> 
  5. </dependency> 

使用 Gradle


  1. compile ‘com.squareup.retrofit2:retrofit:2.1.0‘ 

注意:Retrofit 需要 Java 7 及以上,Android 2.3 及以上

PROGUARD


如果项目使用了 Proguard,需要把下面的内容添加到项目的配置中:

  1. # Platform calls Class.forName on types which do not exist on Android to determine platform. 
  2. -dontnote retrofit2.Platform 
  3. # Platform used when running on RoboVM on iOS. Will not be used at runtime. 
  4. -dontnote retrofit2.Platform$IOS$MainThreadExecutor 
  5. # Platform used when running on Java 8 VMs. Will not be used at runtime. 
  6. -dontwarn retrofit2.Platform$Java8 
  7. # Retain generic type information for use by reflection by converters and adapters. 
  8. -keepattributes Signature 
  9. # Retain declared checked exceptions for use by a Proxy instance. 
  10. -keepattributes Exceptions 

以上是关于Retrofit自定义请求转换器的主要内容,如果未能解决你的问题,请参考以下文章

Android Retrofit 2.0自定义JSONObject Converter

Retrofit 2.0基于OKHttp更高效更快的网络框架 以及自定义转换器

Retrofit--官网2.1.0

Retrofit 2 0 自定义Converter

Retrofit 自定义Cookies

Retrofit 2.6.0:自定义协程 CallAdapterFactory