参考:http://square.github.io/retrofit/#api-declaration。初次接触Retrofit,不免要先看官方文档,看一遍,翻译一遍,再结合实际例子使用,效果会更好些。我也会在一些地方写上注释,便于理解。当然,我的理解可能也有不到位或是偏差的地方,希望能帮忙指正。
一.介绍:
Retrofit将HTTP API 转化成Java中的接口。
下面代码实例中:
1. GitHubService 接口是用户自己定义的API接口。
2. List是服务端返回的Data。
3. {user} 是需要动态赋值的变量。所以最后看到的url地址是:users/testname/repos。
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 的每个Call可以是同步或是异步访问服务端。
Call<List<Repo>> repos = service.listRepos("octocat");
使用注解方式来描述http请求:
1. 支持URL参数替换和查询。(这句话不理解的看例子)
2. 将对象转化为请求体(如json,协议缓冲区?这是什么,我也不大理解)
3. 支持多种数据格式的请求参数和文件上传
二. API 申明
接口方法上的注解和参数表明一个网络请求将怎样被处理。
请求方法
每个方法都必须要有一个 HTTP 注解,注解包含请求方法和相对的URL 。有五个内置注解:分别是 GET, POST, PUT, DELETE, and HEAD。eg:
@GET("users/list")
也可以在URL中指定查询参数。eg:
@GET("users/list?sort=desc")
URL 操作
通过替换块和方法上的参数,一个url请求可以被动态的更新。一个替换块中的内容是通过{}标示,相应的参数必须用@Path注解,名称和{}中的名称相同
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
也可以增加查询参数 eg: 用Query关键词
@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);
比如要传递的参数有id,可以如下:
Map<String,String> myMap = new HashMap<>();
myMap.put("id","123");
请求体
一个对象可以用@Body注解作为http请求体。(对象中的字段就可以传递过去)
@POST("users/new")
Call<User> createUser(@Body User user);
这个对象也可以通过Retrofit 实例中指定的converter 来转化,如果没有增加converter ,只能用RequestBody。
表单编码和不同结构的数据
方法上也可以申明表单编码和不同结构的数据
@FormUrlEncoded 上申明表单编码
不同结构的数据用@Field 形式写键值对
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
不同结构的数据请求要在方法上用@Multipart注解,用@Part申明不同结构的数据. 不同结构的数据可以使用Retrofit的转化器或是实现RequestBody 来处理自己的序列化。
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
头操作
使用@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,如果值为null,这个头被忽略。有值的情况,将会取这个值来更新请求头。
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
需要给每个请求设置请求头的时候,可以用OkHttp interceptor来设置。
同步VS 异步。
每个调用的实例可以是同步或是异步。每个实例只能被用1次,但是通过clone()可以创建一个新的实例来再使用。
在Android上,回调都是在主线程(UI线程),在JVM上,HTTP 请求在哪个线程中,回调就在哪个线程。
三.Retrofit 配置。
Retrofit 是一个将API接口转化成可调用对象的类。Retrofit 会提供一些默认的配置,但是调用者也可以自定义一些配置。
Converters
默认的,Retrofit 仅仅能将HTTP body 反序列化成OkHttp的ResponseBody 并且@Body中仅仅只能接受RequestBody类型。
要扩展其他类型,在Converters中, 有6种可序列化的库可使用。如下:
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 生成API接口的实现,用Gson 将服务端数据反序列化(即:用Gson 解析服务端数据)。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService service = retrofit.create(GitHubService.class);
自定义CONVERTERS
如果你的服务端数据内容格式是Retrofit 不支持的,如(YAML, txt,自定义格式),或是你希望使用一个不同的库来解析数据,你也可以很容易的创建自己的converter:创建一个继承Converter.Factory的类,在构建自己的adapter时候,将它传递进去。
四.实战
现在比较流行的框架是:Retrofit+OkHttp+RxJava。
因为单独使用Retrofit比较难用,然后大神们就对其进行了封装,最后就流行起来了上面那个框架。这个可以网上搜索学习应用到实践当中。