Retrofit 这个东西火了很久了,之前项目一直用别的网络框架没用到。现在也出来学学这个新东西。今天先从Retrofit的官网来看看这个东西的基本概念。
首先从了解到,这是用于Android和java的一个类型安全的Http客户端。官网上有一些说明,有水平的问题,直接弄明白还有有很大难度。
然后看官网上说,Retrofit turns your HTTP API into a Java interface. 大致说Retroifit将我们的Http请求转化成了java 接口形式。
简介
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
上面定义了一个接口。
然后,The Retrofit class generates an implementation of the GitHubService interface. 说Retrofit为我们定义的接口生成一个接口的实现类。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
接着说,Each Call from the created GitHubService can make a synchronous or asynchronous HTTP request to the remote webserver. 创建的每个实现类的请求都可以向远程的服务器发出同步或者异步的请求。
Call<List<Repo>> repos = service.listRepos("octocat");
这就是一个Retroift 请求的基本流程。
Retrofit 使用注释来描述Http请求,接口方法及其注释说明了如何处理请求。每个方法都必须有一个Http注释,他提供了请求方法和相对的URL.有五个内置注解GET、POST、PUT、DELETE、和HEAD.资源的相对URL在注释中指定
@GET("users/list")
@GET("users/list?sort=desc")
在一个方法上可以使用替换块和参数动态的替换请求的URL、替换块是由{and}包围的字母数字字符串,使用相同的字符串必须使用@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请求
@POST("users/new")
Call<User> createUser(@Body User user);
该对象还将使用一个Retrofit实例指定的转换器进行转换,如果没有添加转换器,则只能使用RequestBody
表单编码和多部分
一个方法可以申明为表单编码和multipart data,当@formurlen出现在方法上时,将发送表单编码的数据,每一个键值对都是用@注释,其中包含提供名称和值的对象。
@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);
Multipart 类型的请求使用了一个Retrofit的转换器,或者他们可以实现自己的请求体来处理自己的序列化。
头操作
可以使用@head 注释为方法设置静态头操作
@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,将省略头,否则调用toString()方法,并使用结果。
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
需要添加到每个请求的包头可以使用OkHttp指定。
同步与异步
可以同步或者异步使用调用实例,每个实例只能使用一次,但是调用clone()将创建一个可以使用的新实例,在Android上,回调将在主线程执行,在JVM上,回调将发生在执行Http请求的同一线程上。
Retrofit 的配置
Retrofit 是通过将api接口转换为可以调用的对象的类,默认情况下,Retrofit将为我们的平台提供默认值,也允许自己定制。
转换器
默认情况下,Retrofit只能将Http主体反序列化为OkHttp的ResponseBody 类型,他只能接收ResponseBody 是@body的类型。转换器可以被添加支持其他的类型,六个兄弟模块为您的方便调整为流行的序列化库。
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);
自定义转换器
如果您需要使用一个Retrofit 不支持的内容格式(例如:YAML、txt,、定制格式),或者你希望使用不同的库来实现现有格式,那么你可以很容易的创建自己的转换器,创建一个继承与 Converter的类,在创建适配器和工厂类实例时传入。
最后添加一个自己的简单实例(使用公司的接口):
创建一个接口:
public interface MyService{
@GET("newapi/WorkOrder/ReceptingWorkOrders")
Call<ResponseBody> getWorkOrder(@Query("serviceSpaceId") String serviceSpaceID,
@Query("serviceNetworkId") String serviceNetworkId,
@Query("userID") String userId);
}
创建接口的实例,并调用:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ConstantValue.URL)
.build();
MyService service = retrofit.create(MyService.class);
Call<ResponseBody> call = service.getWorkOrder(
preferences.getString("ServiceSpaceID"),
preferences.getString("ServiceNetworkID"),
preferences.getUserId());
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
LogUtils.e("TAG","response-code:"+response.code());
try {
LogUtils.e("TAG","response-body:"+response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
LogUtils.e("TAG","onFailure:"+t.getMessage());
}
});
最后在onResponse 方法中获取到结果。
参考:http://square.github.io/retrofit/