跳至主要內容

请求参数注解(三)

guodongAndroid大约 3 分钟

前言

在上一篇文章 请求参数注解(二) 中我们学习了 Header 注解,本篇文章我们学习了 Field 相关的注解。

annotation-type

从上图可以看出与 Field 相关的注解有:

  • @Field
  • @FieldMap

@Field

@Field 注解标记HTTP接口方法中的一个参数,表示这个参数是 Form 表单里的一个字段。参数的值、集合或数组中的子项会经过 Retrofit#stringConverter(Type, Annotation[]) 转换,如果没有找到匹配的字符串转换器则使用 Object#toString(),然后再进过 URL 编码。

@Field 注解有两个参数,分别为:

  1. value:必选,表示字段名,
  2. encoded:可选,表示 value 对应的字段名和字段值是否已经经过 URL 编码,默认 false

简单使用示例:

interface Service {
    @FormUrlEncoded
	@POST("foo/bar")
	Call<ResponseBody> method(@Field("lang") String lang);
}

Service service = retrofit.create(Service.class);
service.method("zh");

@Field 注解使用时有以下几点需要注意:

  1. @Field 注解仅能在被 @FormUrlEncoded 注解标记的方法中使用,

  2. 参数值为 null 的话会被忽略,

  3. 参数值为集合或数组时,会忽略其为 null 的子项,如果集合类型不是参数化类型,则抛出异常,即:不能直接使用原始类型:

    // 错误示例
    interface Service {
    	@FormUrlEncoded
    	@POST("foo/bar")
    	Call<ResponseBody> method(@Field("lang") List lang);
    }
    

@FieldMap

@FieldMap 注解标记HTTP接口方法中的一个参数,表示这个参数是 Form 表单里的一个或多个字段。

@FieldMap 注解目前只有一个参数:

  1. encoded:可选,表示字段名和字段值是否已经经过 URL 编码,默认 false

简单使用示例:

interface Service {
    @FormUrlEncoded
	@POST("foo/bar")
	Call<ResponseBody> method(@FieldMap Map<String, String> fields);
}

Service service = retrofit.create(Service.class);
service.method(ImmutableMap.of("foo", "bar", "kit", "kat");
// request body: foo=bar&kit=kat

@FieldMap 注解使用时有以下几点需要注意:

  1. @Field 注解仅能在被 @FormUrlEncoded 注解标记的方法中使用,
  2. 被标注的参数类型必须是 Map,否则抛出异常,
  3. Map 中键的类型必须是 String 类型,否则抛出异常,如果键的值为 null,则抛出异常,
  4. Map 中值没有限定类型,如果值为 null ,则抛出异常,然后会经过 Retrofit#stringConverter(Type, Annotation[]) 转换,如果没有找到匹配的字符串转换器,则使用 Object#toString(),如果转换后的值为 null,则抛出异常,

总结

@Field@FieldMap 注解相对于 Header 相关的注解简单一些,在 Header 相关的注解中我们区分了静态和动态类型,那么本文学习的两个注解都应该属于动态类型,它俩的区别如下表所示:

注解类型适用场景
@Field动态明确字段名,不明确字段值
@FieldMap动态1.字段名和字段值都不明确
2.一次传入多个字段

我们只要记住它俩仅能在 @FormUrlEncoded 注解标记的HTTP接口方法使用,一般就不会出错了。

希望可以帮你更好的使用 Retrofit,happy~