安卓注解使用介绍

在Java中,注解(Annotation)引入始于Java5,用来描述Java代码的元信息,一般状况下注解不会直接影响代码的执行,尽管有些注解能够用来作到影响代码执行。html

在代码文件中使用‘@’字符告诉编译器接下来的是一个注解。注解能够用在类,构造方法,成员变量,方法,参数等的声明中。做用主要是对编译器警告等辅助工具产生影响,若是传递了错误的类型那么编译器就会发出警告,这样就能够在编码和维护的过程当中辅助发现问题,提升开发效率,提高代码质量,也促进造成编码规范。java

安卓开发中用到的注解主要有四个方面:JDK内置注解、JDK自定义注解包、android sdk内置注解、android.support.annotation注解。android

JDK内置注解

以下图,左侧是JDK提供的三个标准注解,在java.lang包内。右侧JDK提供的四个是对自定义注解的支持,在java.lang.annotation包内。数组

@Deprecated是一个标记注解,表示被标记的成员变量或者成员方法已经不建议使用,缘由多是这个方法/变量有缺陷或者在新的SDK中已经不被支持。app

@Override注解在继承过程当中,标识对父类方法的覆盖关系。这个在Java中不是必须的,可是建议在须要的地方强制使用。防止在子类或者父类中误操做修改方法签名或者遗漏相关的代码(kotlin中对于子类覆盖父类方法强制使用override关键字,再也不须要注解标记)。ide

@SuppressWarnings用来抑制编译器生成警告信息,对指定类型的警告保持静默。能够修饰类、方法、方法参数、属性和局部变量,采用就近原则,尽可能放在被须要静默的警告语句附近。接收一个字符串或者一个字符集做为参数(参数详细介绍参考文章),它指示将取消的警告。工具

JDK提供了四种元注解,支持用户对注解进行自定义扩展。自定义注解后面会详细介绍,这里先略过。gradle

Android SDK内置注解

Android SDK注解有两个@SuppressLint和@TargetApi。ui

这两个注解是使用Lint静态检测对应的标记。若是禁用了Lint,用或者不用这些注解都没有太大关系。

@TargetApi:Android工程须要设置所支持的最小的系统版本,Android Studio是在Gradle中设置minSdkVersion的值。若是某个方法或者类被声明须要在某个版本和更高版本的系统上运行,可使用@RequiresApi(requires)声明支持的最小系统版本。当在声明minSdkVersion的工程中使用了requires大于minSdkVersion的类或者方法时,Lint就会报错误提醒,这时候可使用@TargetApi使Lint保持静默,可是要添加代码为低版本的系统提供对应的备选方案,不然在低版本系统上运行会产生崩溃。google

@SuppressLint:上面的@TargetApi注解只针对API版本进行注解,使Lint对版本错误保持静默。@SuppressLint针对的范围更广,经过设置一个参数(identified by the lint issue id)通知Lint对相应的警告⚠和错误❎️保持静默。

@SuppressLint("NewApi"),这个注解能够实现@TargetApi(version)相同的做用,只是没有指定特定的API版本,致使工程师和Lint都不知道响应的范围,容易致使错误,不建议使用。

android support注解

Android Support Library提供com.android.support:support-annotations对Android的注解进行了拓展。下图以v25为例列出了全部定义的46个注解(到v27增长了5个,分别为ColorLong、FontRes、GuardedBy、HalfFloat、NavigationRes)。

  • 其中22个资源类注解,以下:
  • 取值范围类3个注解,IntRange/FloatRange对响应类型的变量或参数规定取值范围,参数有from和to两个;Size对数组的长度约束,参数min/max(含)组合声明数组的长度范围,参数value指定数据的具体长度,参数multiple指定数组长度必须是某个数字的倍数。
  • Android中新引入的替代枚举的注解有IntDef和StringDef,他们惟一的区别一个是int类型,一个是string类型,下面咱们列一下官方API文档中给出的使用方法。

枚举类型的注解的使用,先定义一系列可用的取值,而后定义一个注解使用@IntDef或者@StringDef指定新的注解可用的取值列表。

使用 Enum 的缺点:每个枚举值都是一个对象,在使用它时会增长额外的内存消耗,因此枚举相比于Integer和String会占用更多的内存,较多的使用 Enum 会增长 DEX 文件的大小,会形成运行时更多的开销,使咱们的应用须要更多的空间。特别是分dex的大APP,枚举的初始化很容易致使ANR。

@Retention(SOURCE)
@StringDef({
    POWER_SERVICE,
    WINDOW_SERVICE,
    LAYOUT_INFLATER_SERVICE
})
public @interface ServiceName {}
public static final String POWER_SERVICE = "power";
public static final String WINDOW_SERVICE = "window";
public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
复制代码
@Retention(SOURCE)
@IntDef({
    NAVIGATION_MODE_STANDARD, 
    NAVIGATION_MODE_LIST, 
    NAVIGATION_MODE_TABS
})
public @interface NavigationMode {}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
  ...
public abstract void setNavigationMode(@NavigationMode int mode);
@NavigationMode
public abstract int getNavigationMode();
复制代码

自定义注解

上面的枚举注解,就是自定义注解的例子。自定义注解使用关键字@interface声明,而后用相应的属性修饰。

@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Entity {
    String value();
    String name();
}
复制代码
  • @Documented表示拥有该注解的元素可经过javadoc此类的工具进行文档化。该类型应用于注解那些影响客户使用带注释(comment)的元素声明的类型。若是类型声明是用Documented来注解的,这种类型的注解被做为被标注的程序成员的公共API。
  • @Inherited:表示该注解类型被自动继承
  • @Retention:表示该注解类型的注解保留的时长。可用的参数都在枚举类型RetentionPolicy中给出了定义。当注解类型声明中没有@Retention元注解,则默认保留策略为RetentionPolicy.CLASS。
  • @Target:表示该注解类型的所使用的程序元素类型。可用的参数都在枚举类型ElementType中给出了定义。当注解类型声明中没有@Target元注解,则默认为可适用全部的程序元素。

附录:ButterKnife

使用ButterKnife只须要在module的gradle文件中加入下面代码:

implementation 'com.jakewharton:butterknife:8.4.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
复制代码

在library工程中,直接使用R.xxx.xxx会报“元素值必须为常量表达式”的错误提示,处理步骤以下:

  • 在根gradle文件中添加(版本根据须要变化):
classpath 'com.jakewharton:butterknife-gradle-plugin:8.4.0'
复制代码
  • 在module的gradle中添加:
apply plugin: 'com.jakewharton.butterknife'
复制代码
  • R.xxx.xxx替换成R2.xxx.xxx

参考文章

相关文章
相关标签/搜索