跳至主要內容

请求参数注解(二)

guodongAndroid大约 4 分钟

前言

在上一篇文章 请求参数注解(一) 中我们学习了 @Url@Path 注解,本篇文章我们学习下与 Header 相关的注解。

annotation-type

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

  • @Header
  • @Headers
  • @HeaderMap

@Header 注解标记HTTP接口方法中的一个参数,表示这个参数参与HTTP请求头的构建。参数的值,集合或数组中的子项会经过 Retrofit#stringConverter(Type, Annotation[]) 转换,如果没有找到匹配的字符串转换器则使用 Object#toString()

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

  1. value:必选,表示请求头中的键 Key,
  2. allowUnsafeNonAsciiValues:可选,默认情况下,键和值仅允许 ascii 中的值,如果指定 allowUnsafeNonAsciiValues=true,可以改变上述行为,主要是适用于世界上其他语言,

简单使用示例:

interface Service {
	@GET("foo/bar")
	Call<ResponseBody> method(@Header("Accept-Language") String lang);
}

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

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

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

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

    // 错误示例
    interface Service {
    	@GET("foo/bar")
    	Call<ResponseBody> method(@Header("Accept-Language") List lang);
    }
    
  3. 相同键的请求头不会相互覆盖,所有相同键的请求头都会在HTTP请求中,

@HeaderMap

@HeaderMap 注解也是标记HTTP接口方法中的一个参数,表示这个参数参与HTTP请求头的构建。

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

  1. allowUnsafeNonAsciiValues:可选,其作用与 @Header 注解中的相同,

简单使用示例:

interface Service {
	@GET("foo/bar")
	Call<ResponseBody> method(@HeaderMap Map<String, String> headers);
}

Service service = retrofit.create(Service.class);
service.method(ImmutableMap.of("Accept", "text/plain", "Accept-Charset", "utf-8"));

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

  1. 被标注的参数类型必须是 Map 或者 okhttp3.Headers,否则抛出异常,
  2. 如果是 Map 类型,Map 中键的类型必须是 String 类型,否则抛出异常,
  3. 如果是 Map 类型,Map 中值没有限定类型,但是会经过 Retrofit#stringConverter(Type, Annotation[]) 转换,如果没有找到匹配的字符串转换器,则使用 Object#toString()

@Headers

Headers 注解标记一个HTTP接口方法,表示这个HTTP接口方法所包含的请求头数据。

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

  1. value:必选,字符串数组类型,其子项格式必须为键值对:Key: Value
  2. allowUnsafeNonAsciiValues:可选,其作用与 @Header 注解中的相同,

简单使用示例:

interface Service {
	@GET("foo/bar")
    @Headers({"ping: pong", "kit: kat"})
	Call<ResponseBody> method();
}

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

  1. 数组不能为空,否则抛出异常,
  2. 数组子项格式必须为键值对:Key: Value,缺少 Key:Value 都会抛出异常,

总结

本文学习了 @Header@HeaderMap@@Headers 请求参数注解的简单使用与注意事项,现简单总结下各自的作用与分类。

静态 Header

静态 Header 是我们已经明确知道当前HTTP请求中需要包含的请求头,比如:Content-Type,那么我们就可以以字面量的形式通过 @Headers 注解直接声明在HTTP接口方法之上,这种方式即提升了代码结构,又增强了代码可读性,降低后续的维护成本。

动态 Header

既然有静态 Header,那么就有动态 Header。静态 Header 的优势比较明显,同时劣势也比较鲜明。

当我们知道当前HTTP请求需要包含一些请求头的键,但是不确定请求头的值时,那么我们可以通过 @Header 注解声明在HTTP接口方法的某个参数上,在实际调用HTTP接口方法发起HTTP请求时再传入请求头的值,这种方式在一定程度上增加了请求头设置的灵活性。

当我们不确定当前HTTP请求需要包含哪些请求头,即完全不确定请求头的键和值时,或者请求头的键和值是由外部提供的,那么我们可以通过 @HeaderMap 注解声明在HTTP接口方法的某个参数上,在实际调用HTTP接口方法发起HTTP请求时把请求头信息封装成 Map 类型传入,这种方式极大的提高了请求头设置的灵活性,但是灵活性的提高,对它的一些限制/校验会相应提高,易用性则会相应降低,使用过程中的出错率也会相应增加。

注解类型适用场景
@Header动态 Header明确键,不明确值
@HeaderMap动态 Header1.键和值都不明确
2.一次传入多个 Header
@Headers静态 Header键和值都明确

通过本文的学习,相信在实际工作中使用这两个注解时肯定是信手捏来。

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