Retrofit2中注解简介和常用的注解使用

1.注解简介

Retrofit2.0是在okhttp的基础上进行封装的,网络请求是通过okhttp实现的。Retrofit通过注解的方式,进行网络请求描述。

共22个注解,根据功能大概分为三类:

  • 请求方法类
    GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、HTTP

  • 标记类
    FormUrlEncodedMultipartStreaming

  • 参数类
    HeadersHeaderBodyFieldFieldMapPartPartMapQueryQueryMapPathURL

1.1请求方法类

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<ResponseBody> 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<ResponseBody> getNew(@Path("id") int id);
}

1.2 标记类

  • 表单请求:
    FormUrlEncoded
    Multipart
  • 标记
    Streaming

FormUrlEncoded
请求体是 From 表单

Content-Type:application/x-www-form-urlencoded

Multipart
请求体是支持文件上传的 From 表单

#上传文件使用:Content-Type:multipart/form-data
//传单个文件
@Multipart
@POST("v1/create")
Call<ResponseBody> 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<ResponseBody> create(@Part("pictureName") RequestBody pictureName,   @PartMap Map<String, RequestBody> 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<String, RequestBody> params = new HashMap<>();
params.put("picture\"; filename=\"" + picture.getName() + "", requestFile);
//调接口
create(pictureNameBody, params);

标记
Streaming
响应体的数据用流的形式返回
未使用该注解,默认会把数据全部载入内存,之后通过流获取数据也是读取内存中数据,所以返回数据较大时,需要使用该注解。

1.3 参数类

  • 作用于方法
    Headers
  • 作用于方法参数(形参)
    HeaderBodyFieldFieldMapPartPartMapQueryQueryMapPathURL

Headers

使用 @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 注解动态更新请求头,匹配的参数必须提供给 @Header ,若参数值为 null ,这个头会被省略,否则,会使用参数值的 toString 方法的返回值。

@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

@Body

非表单请求体;
使用 @Body 注解,指定一个对象作为 request body 。
作用:以 Post方式 传递 自定义数据类型 给服务器
注意:如果提交的是一个Map,那么作用相当于 @Field

@POST("users/new")
Call<User> createUser(@Body User user);

@Field

表单字段
作用:发送 Post请求 时提交请求的表单字段
具体使用:与 @FormUrlEncoded 注解配合使用

@Field主要用于Post请求数据。

@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);

@FieldMap

用于post请求,最好传递参数时使用@Field、@FieldMap和@FormUrlEncoded。因为@Query和或QueryMap都是将参数拼接在url后面的,而@Field或@FieldMap传递的参数时放在请求体的。

表单字段,与 Field、FormUrlEncoded 配合;接受 Map<String, String> 类型,非 String 类型会调用 toString() 方法

我们在代码中使用是不是发现了@POST比起@GET多了一个@FromUrlEncoded的注解。
如果去掉@FromUrlEncoded在post请求中使用@Field和@FieldMap,那么程序会抛出Java.lang.IllegalArgumentException: @Field parameters can only be used with form encoding. 的错误异常。
所以如果平时公司如果是Post请求的话,千万别忘记了加这@FromUrlEncoded注解。

/**
  * Map的key作为表单的键
  */
@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded2(@FieldMap Map<String, Object> 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<ResponseBody> 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} 就不适用了,所以文件只能用<b> @Part MultipartBody.Part </b>
         */
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file);

@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload3(@PartMap Map<String, RequestBody> 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<ResponseBody> call3 = service.testFileUpload1(name, age, filePart);
        ResponseBodyPrinter.printResponseBody(call3);

        // @PartMap
        // 实现和上面同样的效果
        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);

@Path

作用:URL地址的缺省值  @Path主要用于Get请求(其他请求也可使用),用于替换Url路径中的变量字符

@GET("users/{user}/repos")
Call<ResponseBody>  getBlog(@Path("user") String user );

@Query@QueryMap

作用:用于 @GET 方法的查询参数(Query = Url 中 ‘?’ 后面的 key-value)

(1)@Query主要用于Get请求数据,用于拼接在拼接在Url路径后面的查询参数,一个@Query相当于拼接一个参数,多个参数中间用,隔开。

(2)@QueryMap:主要的效果等同于多个@Query参数拼接,主要也用于Get请求网络数据。

@GET("/")    
Call<String> cate(@Query("cate") String cate);

@GET("/")    
Call<String> cate(@QueryMap Map map);

@Url

作用:直接传入一个请求的 URL变量 用于URL设置

@Url是动态的Url请求数据的注解。需要注意的是使用@Path时,path对应的路径不能包含”/”,不然每个加到host Url后面的东西都会被省略掉。千万注意了

@GET
Call<ResponseBody> 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等,方便向后台传递数组。


 

猜你喜欢

转载自blog.csdn.net/cmyperson/article/details/86521735