本文旨在向初学者介绍Retrofit2这一网络框架。Retrofit与Retrofit2之间的Api改动较大,目前关于Retrofit的文章有大多是在介绍先前的版本的api。于是此篇文章变应运而生。通过本文你可以了解:
- 使用Retrofit所需要的依赖
- 最新依赖的Jar文件获取方法(search.maven.org)
- 使用Retrofit进行Http请求
- Retrofit 注释Api的简单介绍
Retrofit依赖配置
想要使用Retrofit,需要进行配置的依赖有:
GRADLE:
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.okio:okio:1.8.0'
compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
Retrofit: 基本的依赖,想要用这个网络请求框架,就要添加这个依赖。
okhttp: Retrofit的底层网络访问是使用的okhttp,所以这个也是必须添加的。
okio: 这个是okhttp所用到的依赖库
gson: Retrofit序列化与反序列化所用到的库(可替换)
converter-gson: 与gson对应,用于初始化Retrofit 的(可替换)
小提示:
Retrofit,Volley 等等是封装好了具体请求,线程切换以及数据转换的网络框架。而okhttp是基于http请求的一套客户端,okhttp的职责是和HttpClient,HttpUrlConnection一样的。
如何获取到最新的依赖jar文件
我们通过这个网站:http://search.maven.org 进行搜索,在搜索结果中即可获取最新的jar文件,理论上所有的开源框架都可以在这里找到
使用Retrofit进行Http请求
“A type-safe REST client for Android and Java” 这是Retrofit官网对其的介绍。Retrofit主要的针对的即是REST API,你还不了解REST API是什么的话,先去了解了解吧。
这里我将使用有道翻译的翻译Api 来完成下面的案例。如果你想试一试下面演示的案例,就需要自己去申请一个有道翻译的key。
Retrofit将你的Http请求转换成一个java接口
public interface TranslateService {
@GET("openapi.do?keyfrom=<keyfrom>&key=<key>&type=data&doctype=json&version=1.1")
Call<Translate> listString(@Query("q") String words);
}
简单的分析一下这个接口:
@GET("...") : 这个注释所代表的含义即为Get请求,要是进行Post请求只需要把GET改为Post 即:@POSt("...")。有道翻译的api并不支持Post请求。
@Query("...") : 代表的是增加请求参数, 参数名为注释里的内容,参数值为传入的形参值。
一个简单的例子介绍一下:如果我们传入words的值为"retrofit" 那么在底层我们请求的Url就会变为:http://......&version=1.1&q=retrofit
Retrofit会自动生成一个TranslateService的实现类
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://fanyi.youdao.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
TranslateService service = retrofit.create(TranslateService.class);
TranslateService 创建出的每一个Call都可以产生一个同步或者异步的Http 请求访问远程服务器
//同步方式请求
Response<Translate> response = translateCall.execute();
Translate translate = response.body();
System.out.println(translate.getTranslation().get(0));
//异步方式请求
translateCall.enqueue(new Callback<Translate>() {
@Override
public void onResponse(Call<Translate> call, Response<Translate> response) {
Translate translate = response.body();
System.out.println(translate.getTranslation().get(0));
}
@Override
public void onFailure(Call<Translate> call, Throwable throwable) {
}
});
Retrofit 注释Api的简单介绍
注释在接口的方法以及参数中的作用是指明该Http请求会如何被处理
1. 请求方法
每一个函数都必须指定HTTP 注释,它可以指定请求方法以及相关的URL。这里有五个内建的注释:GET, POST, PUT, DELETE 和 HEAD。相关的URL资源定义在注释里面。
@GET("users/list")
你也可以在URL中指定请求参数
@GET("users/list?srot=desc")
2. 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);
3. 请求体
一个对象可以使用 @Body
注释指定自己为一个HTTP请求的请求体
@Post("users/new")
Call<User> createUser(@Body User user);
这个对象将会被Retrofit的实例指定的转换器所转换。如果Retrofit实例没有添加转换器,那么只有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);
注意:请求头不会相互之间被覆盖,所有的拥有相同名字的请求头都会被包含到整个请求里面。
一个请求头可以使用注释 @Header
动态的更新。相应的参数将会提供给@Header
。如果这个值为空,那么这个请求头将会被忽略。否则toString
方法将会被调用,而且其结果将会赋予这个值
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
如果每一个请求都需要添加多个请求头我们可以使用OkHttp 拦截器
6. 同步vs异步
Call
实例可以被同步或者异步地执行。每一个实例只能使用一次,但是使用clone() 将会创建一个可被使用的新实例。
在Android上,回调方法将会在主线程上执行。在JVM上回调方法将会在和执行HTTP 请求的相同线程上执行。