Retrofit2.0是在okhttp的基础上进行封装的,网络请求是通过okhttp实现的。Retrofit通过注解的方式,进行网络请求描述。
共22个注解,根据功能大概分为三类:
请求方法类GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、HTTP
标记类FormUrlEncoded
、Multipart
、Streaming
参数类Headers
、Header
、Body
、Field
、FieldMap
、Part
、PartMap
、Query
、QueryMap
、Path
、URL
GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、HTTP
共8个。
分别对应 HTTP 的请求方法;(HTTP除外)
接收一个字符串表示接口 path ,与 baseUrl 组成完整的 Url;
可以不指定,结合 @Url 注解使用;
url 中可以使用变量,如 {id} ,并使用 @Path("id") 注解为 {id} 提供值。
目前也只用到了GET和POST。如:
@GET("new/{id}")
Call getNew(@Path("id") int id);
这里说名下HTTP
可用于替代以上 7 个,及其他扩展方法;
有 3 个属性:method、path、hasBody
public interface BlogService{
/**
* method 请求方法,不区分大小写
* path 路径
* hasBody 是否有请求体
*/
@HTTP(method = "get", path = "new/{id}", hasBody = false)
Call getNew(@Path("id") int id);
}
- 表单请求:
FormUrlEncoded
Multipart
- 标记
Streaming
FormUrlEncoded
请求体是 From 表单
Content-Type:application/x-www-form-urlencoded
Multipart
请求体是支持文件上传的 From 表单
#上传文件使用:Content-Type:multipart/form-data
//传单个文件
@Multipart
@POST("v1/create")
Call create(@Part("pictureName") RequestBody pictureName, @Part MultipartBody.Part picture)
RequestBody pictureNameBody = RequestBody.create(MediaType.parse(AppConstants.CONTENT_TYPE_FILE), "pictureName");
File picture= new File(path);
RequestBody requestFile = RequestBody.create(MediaType.parse(AppConstants.CONTENT_TYPE_FILE), picture);
// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part picturePart = MultipartBody.Part.createFormData("picture", picture.getName(), requestFile);
//调接口
create(pictureNameBody, picturePart);
//传多个文件
@Multipart
@POST("v1/create")
Call create(@Part("pictureName") RequestBody pictureName, @PartMap Map map)
RequestBody pictureNameBody = RequestBody.create(MediaType.parse(AppConstants.CONTENT_TYPE_FILE), "pictureName");
File picture= new File(path);
RequestBody requestFile = RequestBody.create(MediaType.parse(AppConstants.CONTENT_TYPE_FILE), picture);
Map params = new HashMap<>();
params.put("picture\"; filename=\"" + picture.getName() + "", requestFile);
//调接口
create(pictureNameBody, params);
标记Streaming
响应体的数据用流的形式返回
未使用该注解,默认会把数据全部载入内存,之后通过流获取数据也是读取内存中数据,所以返回数据较大时,需要使用该注解。
- 作用于方法
Headers
- 作用于方法参数(形参)
Header
、Body
、Field
、FieldMap
、Part
、PartMap
、Query
、QueryMap
、Path
、URL
Headers
使用 @Headers 注解设置固定的请求头,所有请求头不会相互覆盖,即使名字相同。
@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call> widgetList();
@Headers({ "Accept: application/vnd.github.v3.full+json","User-Agent: Retrofit-Sample-App"})
@GET("users/{username}")Call getUser(@Path("username") String username);
@Header
使用 @Header 注解动态更新请求头,匹配的参数必须提供给 @Header ,若参数值为 null ,这个头会被省略,否则,会使用参数值的 toString 方法的返回值。
@GET("user")
Call getUser(@Header("Authorization") String authorization)
@Body
非表单请求体;
使用 @Body 注解,指定一个对象作为 request body 。
作用:以 Post方式 传递 自定义数据类型 给服务器
注意:如果提交的是一个Map,那么作用相当于 @Field
@POST("users/new")
Call createUser(@Body User user);
@Field
表单字段
作用:发送 Post请求 时提交请求的表单字段
具体使用:与 @FormUrlEncoded 注解配合使用
@POST("/form")
@FormUrlEncoded
Call testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);
@FieldMap
表单字段,与 Field、FormUrlEncoded 配合;接受 Map
/**
* Map的key作为表单的键
*/
@POST("/form")
@FormUrlEncoded
Call testFormUrlEncoded2(@FieldMap Map map);
@Part
、@PartMap
post请求时,提交请求的表单字段,与 @ Multipart注解 配合。
和@Field的区别:功能相同,但携带的参数类型更加丰富,包括数据流,所以适用于 有文件上传 的场景
/**
* {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
* 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),
*/
@POST("/form")
@Multipart
Call testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);
/**
* PartMap 注解支持一个Map作为参数,支持 {@link RequestBody } 类型,
* 如果有其它的类型,会被{@link retrofit2.Converter}转换,如后面会介绍的 使用{@link com.google.gson.Gson} 的 {@link retrofit2.converter.gson.GsonRequestBodyConverter}
* 所以{@link MultipartBody.Part} 就不适用了,所以文件只能用 @Part MultipartBody.Part
*/
@POST("/form")
@Multipart
Call testFileUpload2(@PartMap Map args, @Part MultipartBody.Part file);
@POST("/form")
@Multipart
Call testFileUpload3(@PartMap Map args);
// 具体使用
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"), "这里是模拟文件的内容");
// @Part
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt", file);
Call call3 = service.testFileUpload1(name, age, filePart);
ResponseBodyPrinter.printResponseBody(call3);
// @PartMap
// 实现和上面同样的效果
Map fileUpload2Args = new HashMap<>();
fileUpload2Args.put("name", name);
fileUpload2Args.put("age", age);
//这里并不会被当成文件,因为没有文件名(包含在Content-Disposition请求头中),但上面的 filePart 有
//fileUpload2Args.put("file", file);
Call call4 = service.testFileUpload2(fileUpload2Args, filePart); //单独处理文件
ResponseBodyPrinter.printResponseBody(call4);
@Path
作用:URL地址的缺省值
@GET("users/{user}/repos")
Call getBlog(@Path("user") String user );
@Query
、@QueryMap
作用:用于 @GET 方法的查询参数(Query = Url 中 ‘?’ 后面的 key-value)
@GET("/")
Call cate(@Query("cate") String cate);
@GET("/")
Call cate(@QueryMap Map map);
@Url
作用:直接传入一个请求的 URL变量 用于URL设置
@GET
Call testUrlAndQuery(@Url String url, @Query("showAll") boolean showAll);
参数注解小结:
- Map 用来组合复杂的参数;
- Query、QueryMap 与 Field、FieldMap 功能一样,生成的数据形式一样;
Query、QueryMap 的数据体现在 Url 上;
Field、FieldMap 的数据是请求体;- {占位符}和 PATH 尽量只用在URL的 path 部分,url 中的参数使用 Query、QueryMap 代替,保证接口的简洁;
- Query、Field、Part 支持数组和实现了 Iterable 接口的类型, 如 List、Set等,方便向后台传递数组。