在上一节中,实现了
Retrofit
简单的网络请求,当然了,这远远不够,我们需要更加多的功能,这节介绍在Retrofit
中如何定义请求方法
如何描述一个Http
请求方法
就像在上一节中,在一个接口中定义一个Http
请求方法,如下所示,当然了这只是简单的GET
方法,接下来我们将会接触更加多不同类型的方法。
public interface ZhiHuClient {
// https://news-at.zhihu.com/api/4/news/before/20170707
@GET("/api/4/news/before/{date}")
Call<ZhiHuPaseNews> getZhiHuPastNews(@Path("date") String date);
}
Http
请求方法
在上一节中,我们知道可以是使用Java
的annotation
(注释)来描述一个Http
请求方法,在Http
中还有类似的GET
,PUT
,POST
,DELETE
等请求方法,在Retrofit
中也有相对应的注释来实现,例如@GET
,@PUT
,POST
,@DELETE
。下面是一个简单的例子。
public interface UserClient {
@GET("/user/info")
Call<UserInfo> getUserInfo();
@PUT("/user/info")
Call<UserInfo> updateUserInfo(@Body UserInfo userInfo);
@DELETE("/user")
Call<Void> deleteUser();
}
Http
资源定位
另外,我们需要在注释中添加相对路径(相对于BaseUrl
),例如上一节中的@GET("/api/4/news/before/{date}")
,我们只需传相对路径,而不是绝对路径,像https://news-at.zhihu.com/api/4/news/before/20170707
(这里的20170707是动态替换的),这样做的好处是我们只需传一次BaseUrl
(https://news-at.zhihu.com
),而且为我们动态替换BaseUrl
提供了方便。
public interface ZhiHuClient {
// https://news-at.zhihu.com/api/4/news/before/20170707
@GET("/api/4/news/before/{date}")
Call<ZhiHuPaseNews> getZhiHuPastNews(@Path("date") String date);
//全路径
@GET("https://news-at.zhihu.com/api/4/news/latest")
Call<ZhiHuPaseNews> getZhiHuLatestNews();
}
我们来验证一下
//请求的Base url
String API_BASE_URL = "https://news-at.zhihu.com/";
//通过给okhttpClient设置拦截器,能很方便的看到网络返回的数据
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.addInterceptor(httpLoggingInterceptor);
//简单配置ZhiHuClient
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.client(httpClient.build()).build();
ZhiHuClient client = retrofit.create(ZhiHuClient.class);
//传入参数,动态替换url上的参数
// Call<ZhiHuPaseNews> call = client.getZhiHuPastNews("20170707");
//动态替换baseUrl
Call<ZhiHuPaseNews> call = client.getZhiHuLatestNews();
//异步请求
call.enqueue(new Callback<ZhiHuPaseNews>() {
@Override
public void onResponse(Call<ZhiHuPaseNews> call, Response<ZhiHuPaseNews> response) {
//成功返回的回调
//TODO:把返回结果展示
}
@Override
public void onFailure(Call<ZhiHuPaseNews> call, Throwable t) {
//失败返回的回调
//TODO:处理返回失败
}
});
我们可以使从控制台中看到
请求地址的BaseUrl
已经被替换了。
函数名和返回值
上面我们讨论了使用Java
的注释描述Http
请求方法,现在来看看方法Call<ZhiHuPaseNews> getZhiHuPastNews(@Path("date") String date);
这里有三部分:
- 函数名
- 返回值
- 参数
最简单的就是函数名了,像我们平时写代码一样,Retrofi
没有做出限制。
但是返回类型是严格控制的,你必须定义你想从服务器中想要获取的类型,例如,我们想获取知乎过往消息,可以这样Call<ZhiHuPaseNews>
,ZhiHuPaseNews
包含了服务器映射的属性(可以使用GsonFormat生成),然后Retrofi
完成之间的属性转换,如果想要的是原始数据,我们可以这样定义Call<ResponseBody>
,使用ResponseBody
代替ZhiHuPaseNews
,如果不关心服务器返回是什么,我们可以Call<Void> getZhiHuPastNews
,,使用Void
代替ZhiHuPaseNews
根据Http
请求方法的不同,相对应的函数参数也会不一样,例如
@Body
: 把Java
对象当作请求体@Url
: 使用动态URL
@Field
: 以form-urlencoded
发送数据
路径参数(Path Parameters
)
REST API
是基于动态URL
的,通过替换Url
其中的一部分,访问网络,例如https://news-at.zhihu.com/api/4/news/before/20170707
,20170707
是我们指定的访问日期,Retrofit
使我们很方便的替换这些参数,例如:
public interface ZhiHuClient {
@GET("/api/4/news/before/{date}")
Call<ZhiHuPaseNews> getZhiHuPastNews(@Path("date") String date);
}
{date}
表示值是动态的,并在请求时设置,如果在URL
中包含类似{date}
的路径参数,那么就必须在函数参数中添加@Path
参数,@Path
,匹配路径参数(这里指的是@Path("date")
)。
请求参数(Query Parameters
)
动态URL
中,Query Parameters
也是用得很多,例如这样的请求地址http://www.tngou.net/api/info/list?id=3&rows=10
,?id=3
是一个查询参数,与路径参数不同的是,我们不需把注释添加到URL
中,只需简单的把@Query
添加到函数参数中即可,Retrofi
将自动把这些转换到请求方法中。
public interface TngouClient {
// ?id=3&rows=10
@GET("/api/info/list")
Call<TngouHealth> getTngouHealth(@Query("id") Integer id, @Query("rows") Integer rows);
}
如果传入一个null
值,Retrofi
将忽略它。
我们来验证一下:
//请求的Base url
String API_BASE_URL = "http://www.tngou.net/";
//通过给okhttpClient设置拦截器,能很方便的看到网络返回的数据
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.addInterceptor(httpLoggingInterceptor);
//简单配置tngouClient
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.client(httpClient.build()).build();
TngouClient tngouClient = retrofit.create(TngouClient.class);
Call<TngouHealth> call = tngouClient.getTngouHealth(3, 10);
//异步请求
call.enqueue(new Callback<TngouHealth>() {
@Override
public void onResponse(Call<TngouHealth> call, Response<TngouHealth> response) {
}
@Override
public void onFailure(Call<TngouHealth> call, Throwable t) {
}
});
在控制台中可以看到我们的请求地址正是我们所希望的那样
如果第二个参数传入为null
会是怎么样?
Call<TngouHealth> call = tngouClient.getTngouHealth(3, null);
从请求地址可以看到,如果传入null
值,Retrofit
将忽略它,
总结
这节简单的介绍了HTTP方法、返回类型、路径和查询参数等。