Retrofit(一)
一. Retrofit介绍
Retrofit基于Okhttp封装的网络请求框架,网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责网络请求接口的封装.
二. Retrofit简单使用
请求百度URL
1. 添加依赖
implementation 'com.squareup.retrofit2:retrofit:2.2.0'
implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
2. 添加权限
<uses-permission android:name="android.permission.INTERNET"/>
3. 创建请求接口
public interface BaiduInterface {
@GET("http://www.baidu.com")
Call<String> baidu();
}
4. 进行请求
Retrofit retrofit = new Retrofit.Builder()
//baseUrl必须以/结尾
.baseUrl("http://www.baidu.com/")
//添加数据解析,此处解析为字符串类型
.addConverterFactory(ScalarsConverterFactory.create())
//创建
.build();
//获取请求接口的实例
BaiduInterface baiduInterface = retrofit.create(BaiduInterface.class);
//调用请求方法
Call<String> baidu = baiduInterface.baidu();
//进行异步请求
baidu.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
Log.d("RETROFIT", "onResponse: " + response.body());
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Log.d("RETROFIT", "onFailure: ");
}
});
}
请求结果
三. Retrofit的注解
- Retrofit注解共22个,根据功能大概能分为三大类
- 请求方法类
GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、HTTP
- 标记类
FormUrlEncoded、Multipart、Streaming
- 参数类
Headers、Header、Body、Field、FieldMap、Part、PartMap、Query、QueryMap、Path、URL
3.1 请求方法类
GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS
分别对应Http的网络请求方式。
每个注解后都可设置一个Url,或者不设置
public interface BaiduInterface {
@GET("http://www.baidu.com")
Call<String> baidu();
//@GET:采用GET请求方式发送请求
//Call<String> String是请求返回的数据类型
//baidu() 请求方法
}
HTTP
public interface BaiduInterface {
//method 请求方法
//path 路径
//hasBody 是否有请求体
@HTTP(method = "GET" ,path = "new/{id}",hasBody = false)
Call<ResponseBody> getCall(@Path("id") int id);
//url中可以使用变量,如{id},并使用@Path("id")注解为{id}赋值
}
关于Url
- Retrofit将URL分为两个部分,一部分在接口的注解后,一部分在baseUrl中。
//第一部分:在网络请求方法的注解中设置
@GET("s?cl=3&tn=baidutop10&fr=top1000&wd=全明星致敬科比&rsv_idx=2&rsv_dl=fyb_n_homepage&hisfilter=1")
Call<String> baidu();
//第二部分:在baseUrl中
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.baidu.com/")
.addConverterFactory(ScalarsConverterFactory.create())
.build();
网络请求的完整Url=在创建的Retrofit实例时通过baseUrl设置的+网络请求方法注释中设置的
网络请求方法的参数也可设置Url
@GET
Call<String> baidu(@Url String url);
3.2 标记类
FormUrlEncoded
- 每个键都需要@Field注解,在随后的调用需要提供值
public interface RetrofitInterface{
@POST()
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded(@Field("username") String name,@Field("age") int age);
}
Multipart
- 每个键都需要用@part来注解,随后调用需要提供值,适用于有文件上传的场景。
public interface RetrofitInterface{
@POST()
@Multipart
Call<ResponseBody> testFileUpload(@Part("username") RequestBody name,@Part("age") RequestBody age,@Part MultipartBody.Part file);
}
Streaming
- 表示返回的数据以流的形式返回
- 大文件官方建议用@Streaming注解,不然会出现IO异常,小文件可以忽略不注入。如果想进行断点续传的话,可以在此加入header
public interface RetrofitInterface{
@GET
@FormUrlEncoded
Observable<ResponseBody> downloadFile(@Url String url);
}
3.3 网络请求参数
-
@Headers
- 添加请求头
- 网络请求接口的方法
-
@Header
- 添加不固定值的请求头
- 参数列表
// @Header @GET("user") Call<User> getUser(@Header("Authorization") String authorization) // @Headers @Headers("Authorization: authorization") @GET("user") Call<User> getUser() // 以上的效果是一致的。 // 区别在于使用场景和使用方式 // 1. 使用场景:@Header用于添加不固定的请求头,@Headers用于添加固定的请求头 // 2. 使用方式:@Header作用于方法的参数;@Headers作用于方法
-
@Body
-
用于非表单请求体,以Post方式传递自定义数据类型给服务器
-
如果提交一个Map,那么作用相当于@Field,不过Map要经过FormBody.Builder类处理成为符合okhttp格式的表单
-
参数列表
-
FormBody.Builder builder = new FormBody.Builder(); builder.add("key","value");
-
-
@Field @FieldMap
-
向POST表单传入键值对
-
参数列表
-
作用:发送Post请求时提交请求的表单字段,与@FormUrlEncoded注解配合使用
-
public interface RetrofitInterface { /** *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded) * <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值 */ @POST("/form") @FormUrlEncoded Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age); } //具体使用 Call<ResponseBody> call1 = service.testFormUrlEncoded1("Carson", 24);
-
public interface RetrofitInterface { /** *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded) * <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值 */ @POST("/form") @FormUrlEncoded Call<ResponseBody>testFormUrlEncoded2(@FieldMap Map<String, Object> map); } //具体使用 Map<String, Object> map = new HashMap<>(); map.put("username", "Carson"); map.put("age", 24); Call<ResponseBody> call2 = service.testFormUrlEncoded2(map);
-
-
@Part @PartMap
-
用于表单字段,适用于有文件上传的情况
-
参数列表
-
与@Multipart配合使用
-
public interface RetrofitInterface { /** * {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型 * 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息), */ @POST("/form") @Multipart Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file); } MediaType textType = MediaType.parse("text/plain"); RequestBody name = RequestBody.create(textType, "Carson"); RequestBody age = RequestBody.create(textType, "24"); RequestBody file = RequestBody.create(MediaType.parse("application/octet-stream"), "这里是模拟文件的内容"); //调用 MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt", file); Call<ResponseBody> call3 = service.testFileUpload1(name, age, filePart); ResponseBodyPrinter.printResponseBody(call3);
-
public interface RetrofitInterface { /** * PartMap 注解支持一个Map作为参数,支持 {@link RequestBody } 类型, * 如果有其它的类型,会被{@link retrofit2.Converter}转换,如后面会介绍的 使用{@link com.google.gson.Gson} 的 {@link retrofit2.converter.gson.GsonRequestBodyConverter} * 所以{@link MultipartBody.Part} 就不适用了,所以文件只能用<b> @Part MultipartBody.Part </b> */ @POST("/form") @Multipart Call<ResponseBody> testFileUpload2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file); } MediaType textType = MediaType.parse("text/plain"); RequestBody name = RequestBody.create(textType, "Carson"); RequestBody age = RequestBody.create(textType, "24"); RequestBody file = RequestBody.create(MediaType.parse("application/octet-stream"), "这里是模拟文件的内容"); //调用 Map<String, RequestBody> fileUpload2Args = new HashMap<>(); fileUpload2Args.put("name", name); fileUpload2Args.put("age", age); //这里并不会被当成文件,因为没有文件名(包含在Content-Disposition请求头中),但上面的 filePart 有 //fileUpload2Args.put("file", file); Call<ResponseBody> call4 = service.testFileUpload2(fileUpload2Args, filePart); //单独处理文件 ResponseBodyPrinter.printResponseBody(call4);
-
-
@Query @QueryMap
- @Query和@QueryMap的数据体现在Url上
- 参数列表
-
@Path
-
Url缺省值
-
参数列表
-
@GET("group/{id}/users") Call<List<User>> groupList(@Path("id") int groupId);
-
-
@Url
-
Url设置
-
public interface RetrofitInterface { @GET Call<String> baidu(@Url String url); }
-