添加依赖 https://github.com/square/retrofit
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
如何使用
- 注一:Retrofit2 的baseUlr 必须以 /(斜线) 结束,不然会抛出一个IllegalArgumentException,所以如果你看到别的教程没有以 / 结束,那么多半是直接从Retrofit 1.X 照搬过来的。
- 注二:上面的 注1 应该描述为 baseUrl 中的路径(path)必须以 / 结束, 因为有些特殊情况可以不以/结尾,比如 其实这个 URL https://www.baidu.com?key=value用来作为baseUrl其实是可行的,因为这个URL隐含的路径就是 /(斜线,代表根目录) ,而后面的?key=value在拼装请求时会被丢掉所以写上也没用。之所以 Retrofit 2 在文档上要求必须以 /(斜线) 结尾的要求想必是要消除歧义以及简化规则。
- 接口定义 以获取指定id的Blog为例:
public interface BlogService {
@GET("blog/{id}")
Call<ResponseBody> getBlog(@Path("id") int id);
}
注意,这里是interface不是class,所以我们是无法直接调用该方法,我们需要用Retrofit创建一个BlogService的代理对象。
- 接口调用
Call<ResponseBody> call = service.getBlog(2);
// 用法和OkHttp的call如出一辙,
// 不同的是如果是Android系统回调方法执行在主线程
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
Retrofit注解详解
Android中注解的使用十分广泛,没了解过的可以先凑活看看
第一类:HTTP请求方法
以上表格中的除HTTP以外都对应了HTTP标准中的请求方法,而HTTP注解则可以代替以上方法中的任意一个注解,有3个属性:method、path,hasBody
public interface BlogService {
/**
* method 表示请求的方法,区分大小写
* path表示路径
* hasBody表示是否有请求体
*/
@HTTP(method = "GET", path = "blog/{id}", hasBody = false)
Call<ResponseBody> getBlog(@Path("id") int id);
}
第二类:标记类
第三类:参数类
方法参数这部分也很多,为了方便理解和记忆,有些可以看成是相同的,像 @Field 和 @FieldMap,@Query 和 @QueryMap,@Part 和 @PartMap,@Headers 和 @Header(这两个和前面三对还有些区别)。
- @Path(GET请求)
@GET("api/{Country}")
Call<List<Province>> getProvinces(@Path("Country") String country);
通过 Path 注解,可以将 GET 中{Country}部分进行动态替换,这个很好理解。
- @Url(GET请求)
用于替换url中某个字段,例如:
@GET("group/{id}/users")
Call<Book> groupList(@Path("id") int groupId);
@Url 注解同样可设置 URL,达到上面 GET 后面设置的效果。
@GET
Call<List<Province>> getProvinces(@Url String url);
- @Query 和 @QueryMap(GET请求)
如,我要访问下面这个URL,在 ?之后是查询参数,这些参数就可以通过 @Query 来动态设定。
http://fy.iciba.com/ajax.php?a=fy&f=auto&t=auto&w=hello%20world
查询参数分解为键值对:
key——–value
a————-fy
f————auto
t————auto
w———hello%20world
使用 @Query 对每一个键值对进行参数设置,当有多个键值对时,就可以通过 @QueryMap
public interface QueryService {
//baseurl 为http://fy.iciba.com/
@GET("ajax.php")
Call<Message> getMessage(@Query("a") String param1,
@Query("f") String param2, @Query("t") String param3,
@Query("w") String param4);
@GET("{message}")
Call<Message> getMessage(@QueryMap Map<String, String> params);
}
使用
//getService 创建接口实例的方法,重点看下面的代码
QueryService getService = (QueryService) getService("http://fy.iciba.com/", GetService.class);
/**
* url
* http://fy.iciba.com/ajax.php?a=fy&f=auto&t=auto&w=hello%20world
*/
//@Query
Call<Message> call = getService.getMessage("fy","auto","auto","hello%20world");
//@QueryMap
Map<String, String> paramsMap = new HashMap<>();
paramsMap.put("a", "fy");
paramsMap.put("f", "auto");
paramsMap.put("t", "auto");
paramsMap.put("w", "hello%20world");
Call<Message> call = getService.getMessage(paramsMap);
- @Header 和 @Headers(POST请求)
这两个注解都是作用于请求头,区别在于 @Header 用于不固定的请求头,@Headers 用于添加固定请求头,关于请求头的概念,需要去了解下消息结构的 header 部分。
@Headers 设置请求头的Content-type,即设置编码格式,固定请求头 意思是使用这个请求接口的编码格式都是一样的。
public interface HeaderService {
@POST("api/users")
Call<ResponseInfo> uploadUser(@Header("Content-Type") String contentType,@Field("username") String username);
}
@Header 设定动态设置请求头编码格式,在调用方式,通过参数传递
public interface HeaderService {
@POST("api/users")
Call<ResponseInfo> uploadUser(@Header("Content-Type") String contentType,@Field("username") String username);
}
调用
Call call = service.uploadNewUser(“application/x-www-form-urlencoded;charset=UTF-8”,”Ralf”);
Gson与Converter
在默认情况下Retrofit只支持将HTTP的响应体转换换为ResponseBody,而Converter就是Retrofit为我们提供用于将ResponseBody转换为我们想要的类型,
有了Converter之后我们就可以写把我们的第一个例子的接口写成这个样子了:
public interface BlogService {
@GET("blog/{id}")
Call<Result<Blog>> getBlog(@Path("id") int id);
}
当然只改变泛型的类型是不行的,我们在创建Retrofit时需要明确告知用于将ResponseBody转换我们泛型中的类型时需要使用的Converter,引入Gson支持:
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
通过GsonConverterFactory为Retrofit添加Gson支持:
Gson gson = new GsonBuilder()
//配置你的Gson
.setDateFormat("yyyy-MM-dd hh:mm:ss")
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:4567/")
//可以接收自定义的Gson,当然也可以不传
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
retrofit2 + RxJava2结合更香哦
具体的实现这里就不讲了,但retrofit2 + RxJava2是十分常见的网络请求实现方式哦