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
介绍
Retrofit
将 HTTP API
转换为 Java
的接口:
- public interface GitHubService {
- @GET("users/{user}/repos")
- Call<List<Repo>> listRepos(@Path("user") String user);
- }
使用 Retrofit
类生成 GitHubService
的实例:
- Retrofit retrofit = new Retrofit.Builder()
- .baseUrl("https://api.github.com/")
- .build();
-
- GitHubService service = retrofit.create(GitHubService.class);
在 GitHubService
实例上的每次调用都会产生一个到远程服务的同步、或异步的 HTTP
的请求:
- Call<List<Repo>> repos = service.listRepos("octocat");
使用注解描述 HTTP
请求:
-
支持
URL
参数的占位符,支持请求参数 -
对象和
response body
的转换(例如:JSON
等) -
Multipart
请求体和文件上传
API 描述
接口方法和参数上的注解标识了如何处理一个请求。
请求方法
每个方法必须使用一个注解来提供请求类型和相对 URL
地址。请求类型注解一共有五个:GET
,POST
,PUT
,DELETE
,HEAD
。注解中也可以指定相对的 URL
地址:
- @GET("users/list")
在 URL
中,也可以指定查询参数:
- @GET("users/list?sort=desc")
URL 处理
请求的 URL
中,可以使用占位符块和方法中的参数,对 URL
进行动态的更新。一个占位符块就是在 {
和 }
之间包含的数字和字母。必须使用同样的数字和字母,使用 @Path
注解来申明相应的参数:
- @GET("group/{id}/users")
- Call<List<User>> groupList(@Path("id") int groupId);
当然,也可以添加查询参数:
- @GET("group/{id}/users")
- Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
复杂的查询参数(例如 Map
类型)的示例:
- @GET("group/{id}/users")
- Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
请求体
可以使用 @Body
注解来把一个对象指定为 HTTP
的 BODY
:
- @GET("group/{id}/users")
- Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
也可以通过给 Retrofit
的实例指定转换器的方式对对象进行转换。如果没有添加转换器,仅能使用 RequestBody
。
表单的 ENCODED 和 MULTIPART
也可以申明方法来发送 form-encoded
和 multipart
的数据。
当方法上存在 @FormUrlEncoded
注解时,就会发送 form-encoded
的数据。@Filed
包含了键值对的键名称,后面的对象提供了键值对的值:
- @FormUrlEncoded
- @POST("user/edit")
- Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
当方法上存在 @Multipart
注解时,就会发送 multipart
的数据,各部分使用 @Part
注解进行申明:
- @Multipart
- @PUT("user/photo")
- Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
multipart
的各部分要么使用 Retrofit
的转换器,要么实现 RequestBody
,用这样的方式来实现各自的序列化。
HEADER 处理
可以使用 @Headers
注解来为某个方法设置静态的头:
- @Headers("Cache-Control: max-age=640000")
- @GET("widget/list")
- Call<List<Widget>> widgetList();
- @Headers({
- "Accept: application/vnd.github.v3.full+json",
- "User-Agent: Retrofit-Sample-App"
- })
- @GET("users/{username}")
- Call<User> getUser(@Path("username") String username);
注意:header中的各个部分不能相互覆盖。所有相同名称的header都会被包含在请求中。
也可以使用 @Header
注解对头部内容进行动态的更新。对应的参数必须由 @Header
进行提供。如果值为 null
,那么将被忽略。如果不为 null
,值将会使用 toString()
方法,最终使用 toString()
方法返回的值:
- @GET("user")
- Call<User> getUser(@Header("Authorization") String authorization)
如果要给每个请求都添加头部,那么,可以使用 OkHttp interceptor
进行指定。
同步 VS 异步
Call
对象的实例上,即可以使用同步,也可以使用异步。它的每个实例只能使用一次,使用 clone()
方法就可以创建一个新的实例来使用。
在 Android
中,回调方法会在主线程中执行。在 JVM
中,回调将和执行 HTTP
请求发生在同一线程。
Retrofit 配置
默认地,Retrofit
有健全的默认值,但是,也可以自定义配置。
转换器
默认地,Retrofit
只会把 HTTP body
的内容反序列化到 OKHttp
的 ResponseBody
类型中,并且它只接收用 @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
作为反序列化的工具:
- Retrofit retrofit = new Retrofit.Builder()
- .baseUrl("https://api.github.com")
- .addConverterFactory(GsonConverterFactory.create())
- .build();
-
- GitHubService service = retrofit.create(GitHubService.class);
自定义转换器
如果你需要与之通信的 API
使用了 Retrofit
不支持的内容格式(例如:YAML
,文本,自定义格式等),或者你想使用一个其它的库来实现一个已经存在的格式,那么,就需要创建自己的转换器,这是一件非常简单的事情。创建一个类继承 Converter.Factory
类,然后,在构建适配器时,把它传给实例就可以了。
下载
使用 maven
- <dependency>
- <groupId>com.squareup.retrofit2</groupId>
- <artifactId>retrofit</artifactId>
- <version>2.1.0</version>
- </dependency>
使用 Gradle
- compile ‘com.squareup.retrofit2:retrofit:2.1.0‘
注意:Retrofit 需要 Java 7 及以上,Android 2.3 及以上
PROGUARD
如果项目使用了 Proguard
,需要把下面的内容添加到项目的配置中:
- # Platform calls Class.forName on types which do not exist on Android to determine platform.
- -dontnote retrofit2.Platform
- # Platform used when running on RoboVM on iOS. Will not be used at runtime.
- -dontnote retrofit2.Platform$IOS$MainThreadExecutor
- # Platform used when running on Java 8 VMs. Will not be used at runtime.
- -dontwarn retrofit2.Platform$Java8
- # Retain generic type information for use by reflection by converters and adapters.
- -keepattributes Signature
- # Retain declared checked exceptions for use by a Proxy instance.
- -keepattributes Exceptions
以上是关于Retrofit自定义请求转换器的主要内容,如果未能解决你的问题,请参考以下文章
Android Retrofit 2.0自定义JSONObject Converter