原文链接:http://square.github.io/retrofit/#api-declaration
英文不好,翻译只是为了让自己好好看一遍文章。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
一、简介:
Retrofit把HTTP的API转成java的接口(接口的名称是GitHubService,方法是listRepos):
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的请求:
1. 支持使用参数替代url的某个字段,支持查询参数。
2. 可以把对象转成http请求的body,如JSON,protocol buffers.
3. 多个请求body,和上传的功能
二、API声明
接口的方法和参数,阐明如何处理http请求。
1. 请求方法
接口的每一个方法都必须要有一个HTTP的注释,提供HTTP的方法和相对的url。有5个内置的HTTP方法的注释:GET, POST, PUT, DELETE 和 HEAD。()括号里面的是相对url:
@GET("users/list")
也可以在相对url中定义查询参数:
@GET("users/list?sort=desc")
2.URL说明
注释中的url可以使用占位符,再使用方法中的参数来代替。占位符的格式是: {name},方法中,用于替代占位符的参数需要使用@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);
3.请求体body
可以使用类的对象作为请求体,需要添加@Body的注释:
@POST("users/new")
Call<User> createUser(@Body User user);
类的对象将被Retrofit定义的转换类转换成body参数。如果没有添加转换类,则只能使用RequestBody
4.表单和多个请求体
接口的方法可以发送表单和多个请求体数据。
使用@FormUrlEncoded发送表单数据。每个键值对,使用@Field来表示键,参数表示值:
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
使用@Multipart表示支持多个请求体。每个请求体使用@Part来表示:
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
请求体可以使用Retrofit的转换类,或者自己实现RequestBody来转换。
5.头部说明
可以使用@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);
相同名字的头部不会被覆盖。如果两个头部名字相同,那他们都会被传到HTTP的头部中去。
头部也可以使用参数动态的更新。参数必须要有@Header的注释。如果参数为空,则头部被忽略。否则,会调用参数的toString方法,作为头部。
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
头部如果要加到每个请求中,可以使用OkHttp interceptor
6.同步和异步
Call的实例,可以被同步或异步调用。每个实例只可以被调用一次。但是,调用clone()的方法,又可以创建一个可以被调用的实例。
在android中,回调函数callbacks将会在UI的主线程中执行。在JVM中,回调将会和调用的方法同一个线程。
三、配置Retrofit
通过Retrofit,可以把API的接口转成可以调用的实例。Retrofit会有一个默认的配置,但是你也可以根据你的需要来配置。
1.转换器
默认情况下,Retrofit只能把http的body序列化成OkHttp的ResponseBody类型,并且@body的参数只接受ResponseBody的类型。
添加转换器可以支持其他的类型。下面提供了六个常用的序列号转换器:
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);
2.自定义转换器
如果需要Retrofit不支持的格式,如YAML, txt, 自定义类型等。 或者想用使用不同的库来实现存在的类型,你可以很轻易的创建一个转换器。只需要创建一个类,继承Converter.Factory。并在创建retrofit的时候赋值。