注解深入浅出(五Retrofit 中的注解)

Posted 持续学习刻意练习

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了注解深入浅出(五Retrofit 中的注解)相关的知识,希望对你有一定的参考价值。

第二章注解深入浅出

五、Retrofit 中的注解

retrofit-2.9.0 共有 25 个注解,根据功能大概分为三类:

  • 请求方法类
  • 标记类
  • 参数类
  • 其他类

5.1 请求方法类注解

有 8 个,分别是:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、HTTP

序号名称作用备注
1GET
  • 用于发送一个 GET 请求
  • GET 注解一般必须添加相对路径或绝对路径或全路径,如果不想在 GET 注解后添加请求路径则可以在方法的第一个参数中用 @Url 注解添加请求路径
  • 分别对应 HTTP 的请求方法
  • 接收一个字符串表示接口 path 与 baseUrl 组成完成的 Ur
  • 可以不指定,结合 @Url 注解使用
  • url 中可以使用变量,如 id,并使用 @Path("id") 注解为 id 提供值
2POST
  • 用于发送一个 POST 请求
  • POST 注解一般必须添加相对路径或绝对路径或全路径,如果不想在 POST 注解后添加请求路径则可以在方法的第一个参数中用 @Url 注解添加请求路径
3PUT
  • 用于发送一个 PUT 请求
  • PUT 注解一般必须添加相对路径或绝对路径或全路径,如果不想在 PUT 注解后添加请求路径则可以在方法的第一个参数中用 @Url 注解添加请求路径
4DELETE
  • 用于发送一个 DELETE 请求
  • DELETE 注解一般必须添加相对路径或绝对路径或全路径,如果不想在 DELETE 注解后添加请求路径,则可以在方法的第一个参数中用 @Url 注解添加请求路径
5PATCH
  • 用于发送一个 PATCH 请求
  • 在 URL 路径段中替换指定的参数值,使用 String.valueOf() 和 URL 编码将转换为字符串
  • 使用该注解定义的参数的值不可为空
  • 参数值默认使用 URL 编码
6HEAD
  • 用于发送一个 HEAD 请求
  • HEAD 注解一般必须添加相对路径或绝对路径或全路径,如果不想在 HEAD 注解后添加请求路径,则可以在方法的第一个参数中用 @Url 注解添加请求路径
7OPTIONS
  • 用于发送一个 OPTIONS 请求
  • OPTIONS 注解一般必须添加相对路径或绝对路径或全路径,如果不想在 OPTIONS 注解后添加请求路径,则可以在方法的第一个参数中用 @Url 注解添加请求路径
8HTTP
  • 作用于方法,用于发送一个自定义的 HTTP 请求
  • 可用于替代以上 7 个以其它扩展方法
  • 有 3 个属性:method、path、hasBody

5.2 标记类注解

有 3 个,分别是 FormUrlEncoded、Multipart、Streaming

序号名称作用
1FormUrlEncoded
  • 用于修饰 Field 注解和 FieldMap 注解
  • 使用该注解,表示请求正文将使用表单网址编码。字段应该声明为参数,并用 @Field 注释或 @FieldMap 注释
  • 使用 FormUrlEncoded 注释的请求将具 “application / x-www-form-urlencoded”MIME 类型。字段名称和值将先进行 UTF-8 进行编码,再根据 RFC-3986 进行 URI 编码
2Multipart
  • 作用于方法
  • 使用该注解表示请求体是多部分的,每一部分作为一个参数且用 Part 注释声明,例如:文件上传
3Streaming
  • 作用于方法
  • 处理返回 Response 的方法的响应体,即没有将 body() 转换为 byte[]
  • 未使用该注解,默认会把数据全部载入内存,之后通过流获取数据也是读取内存中数据,所以返回数据较大时,需要使用该注解

5.3 参数注解

有 11 个,分别是:Body、Field、FieldMap、Part、PartMap、HeaderMap、Path、Query、QueryMap、QueryName、Url

序号名称作用
1Body
  • 作用于方法的参数
  • 使用该注解定义的参数不可为 null
  • 当你发送一个 post 或 put 请求,但是又不想作为请求参数或表单的方式发送请求时,使用该注解定义的参数可以直接传入一个实体类,retrofit 会通过 convert 把该实体序列化并将序列化后的结果直接作为请求体发送出去
2Field
  • 作用于方法的参数
  • 用于发送一个表单请求
  • 用 String.valueOf() 把参数值转换为 String,然后进行 URL 编码,当参数值为 null 值时,会自动忽略,如果传入的是一个 List 或 Array,则为每一个非空的 item 拼接一个键值对,每一个键值对中的键是相同的,值就是非空 item 的值,如果 item 的值有空格,在拼接时会自动忽略
3FieldMap
  • 作用于方法的参数
  • 用于发送一个表单请求
  • map 中每一项的键和值都不能为空,否则会抛出 IllegalArgumentException 异常
4Part
  • 作用于方法的参数,用于定义 Multipart 请求的每个 part
  • 使用该注解定义的参数,参数值可以为空,为空时则忽略
  • 使用该注解定义的参数类型有以下三种方式可选
    1. 如果类型是 okhttp3.MultipartBody.Part,内容将被直接使用,省略 part 中的名称,即 @PartMultipartBody.Part part
    2. 如果类型是 RequestBody,那么该值将直接与其内容类型一起使用,在注解中提供 part 名称,例如:@Part ("foo") RequestBody foo
    3. 其他对象类型将通过使用转换器转换为适当的格式,在注解中提供 part 名称,例如:@Part ("foo") Image photo
5PartMap
  • 作用于方法的参数,以 map 的方式定义 Multipart 请求的每个 part
  • map 中每一项的键和值都不能为空,否则会抛出 IllegalArgumentException 异常
  • 使用该注解定义的参数类型有以下两种方式可选:
    1. 如果类型是 RequestBody,那么该值将直接与其内容类型一起使用
    2. 其他对象类型将通过使用转换器转换为适当的格式
6HeaderMap
  • 作用于方法的参数,用于添加请求头
  • 以 map 的方式添加多个请求头,map 中的 key 为请求头的名称,value 为请求头的值,且 value 使用 String.valueOf() 统一转换为 String 类型
  • map 中每一项的键和值都不能为空,否则会抛出 IllegalArgumentException 异常
7Path
8Query
  • 作用于方法的参数
  • 用于添加查询参数,即请求参数
  • 动态拼接一个参数到 URL 后
  • 参数值通过 String.valueOf() 转换为 String 并进行 URL 编码
  • 使用该注解定义的参数,参数值可以为空,为空时忽略该值,当传入一个 List 或 Array 时,为每个非空 item 拼接请求键值对,所有的键时统一的
9QueryMap
  • 作用于方法的参数
  • 以 map 的形式添加查询参数,即请求参数
  • 动态拼接多个参数到 URL 后
  • 参数的键和值都通过 String.valueOf() 转换为 String 格式
  • map 的键和值默认进行 URL 编码
  • map 中每一项的键和值都不能为空,否则会抛出 IllegalArgumentException 异常
10QueryName
  • 作用于方法的参数
  • 动态拼接无值参数到 URL 后
11Url
  • 作用于方法参数
  • 用于添加请求的接口地址

5.4 其他注解

有 3 个,分别是:Header、Headers、Tag

序号名称作用
1Header
  • 作用于方法的参数,用于添加请求头
  • 使用该注解定义的请求头可以为空,当为空时,会自动忽略,当传入一个 List 或 array 时,为拼接每个非空的 item 的值到请求头中
  • 具有相同名称的请求头不会相互覆盖,而是会照样添加到请求头中
2Headers
  • 作用于方法,用于添加一个或多个请求头
  • 具有相同名称的请求头不会互相覆盖,而是照样添加到请求头中
3Tag

5.5 注意事项

  1. 以上部分注解真正的实现在 ParameterHandler 类中,每个注解的真正实现都是 ParameterHandler 类中的一个 final 类型的内部类,每个内部类都对各个注解的使用要求做了限制,比如参数是否为空,键和值是否为空等。

  2. FromUrlEncoded 注解和 Multipart 注解不能同时使用,否则会抛出 methodError(“Only one encoding annotation is allowed”),可在 ServiceMethod 类中 parseMethodAnnotation() 方法中找到不能同时使用的具体原因。

  3. Path 注解与 Url 注解不同时使用,否则会抛出 parameterError(p, “@Path parameters may not be used with @Url”),可在 ServiceMethod 类中找到不能同时使用的具体代码,其实原因也很好理解,Path 注解用于替换 url 路径中的参数,这就要求在使用 path 注解时,必须已经存在请求路径,不然没法替换路径中指定的参数,而 Url 注解是在参数中指定的请求路径的,这个时候指定请求路径已经晚了,path 注解找不到请求路径,更别提更换请求路径中的参数了。

  4. 对于 FieldMap、HeaderMap、PartMap、QueryMap 这四种作用于方法的注解,其参数类型必须为 Map 的实例,且 key 的类型必须为 String 类型,否则会抛出异常,以 PartMap 注解为例,会抛出 parameterError(p, “@PartMap keys must be of type String:” + keyType)

  5. 使用 Body 注解的参数不能使用 form 或 multi-part 编码,即如果为方法使用了 FormUrlEncoded 或 Multipart 注解,则方法的参数中不能使用 Body 注解,否则会抛出异常 parameterError(p, “@Body parameters cannot be used with form or multi-part encoding”)

以上是关于注解深入浅出(五Retrofit 中的注解)的主要内容,如果未能解决你的问题,请参考以下文章

Retrofit 中的注解以及如何自定义接口方法注解

理解Android中的注解与反射

Java反射学习总结五(Annotation(注解)-基础篇)

Java反射学习总结五(Annotation(注解)-基础篇)

五Spring中的@Import注解

注解深入浅出(一注解 Annotations)