原文链接: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的时候赋值。