安卓注解那些事儿

博客: 安卓之家
微博: 追风917
CSDN: 蒋朋的家
简书: 追风917

每日一景

Annotation


Annotation就是注解了,JDK1.5新增加功能,该功能可用于类,构造方法,成员变量,方法,参数等的声明中,比如常见的@Override,butterknife库里的@Bind, 该功能并不影响程序的运行,主要作用就是提供类型安全,对编译器警告等辅助工具产生影响。

关于java注解的详细介绍,包括概念,作用,分类,解析及几个常用的安卓库的原理解析等请来这里查看:Java Annotation 及几个常用开源项目注解原理简析

Android Annotation


Android Annotation是以Support Library的形式给我们提供的,从安卓19.1开始出现,该包在sdk目录\Sdk\extras\android\m2repository\com\android\support\support-annotations下:

android annotation

api版本23下,android studio里是直接可以使用的,不用添加依赖库,以前的api可能需要,请酌情增删。api23暂时有39个注解,可以这里查看:

buildtool23

安卓注解有8种类型,分别是Nullness注解、资源类型注解、线程注解、变量限制注解、权限注解、结果检查注解、CallSuper注解、枚举注解(IntDef和StringDef)。

下面简单摘录几个,以飨读者:

Nullness注解


包括@NoNull和@Nullable,这里以@NoNull为例说明:

先看下@NoNull的源码:

1
2
3
4
@Retention(CLASS)
@Target({METHOD, PARAMETER, FIELD})
public @interface NonNull {
}

这里我们知道,@NoNull编译到类文件里,应用于方法,参数和成员变量,下面我们先来一发:

1
2
3
4
5
6
7
8
9
10
11
public class MainActivity extends Activity {
@NonNull private String str;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

str = null;
}
}

我们给成员变量str加上了@NoNull注解,也就是str不能为null,而后面我们把str初始化为null,此时as编译器这样提示我们:

nonull

也就是str不能为空,这就像是一种约定,很像c语言里的断言assert。这样有什么好处呢?这样可以避免后面的频繁判断str是否为空的操作,如果和别的项目配合呢,可能会出现某些bug,而使用注解可以很好的用于团队合作,项目维护起来也方便。

资源类型注解


此类注解以Res结尾,比如@BoolRes, @IdRes, @IntegerRes, @StringRes, @ColorRes等,这里以@ColorRes为例说明

先看下@ColorRes的源码:

1
2
3
4
5
@Documented
@Retention(CLASS)
@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE})
public @interface ColorRes {
}

这里我们知道,@ColorRes在编译时生效,使用于方法,参数和成员变量和局部变量,下面我们再来一发:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

getCurColor(R.id.ic_launcher);
}

void getCurColor(@ColorRes int color) {
Toast.makeText(this, "Color: " + getString(color), Toast.LENGTH_LONG).show();
}
}

我们给getColor函数的参数color加上了@ColorRes注解,即该参数是一个颜色资源,而上面我们上面传递的是id资源,此时as编译器这样提示我们:

color

我们这样调用就ok的

1
getCurColor(R.color.material_blue_grey_900);

:看到了吧,好玩吗?
:嗯,as很好很强大,,,
:好的,我们继续。

权限注解


直接上代码了,源码自己查阅咯

1
2
@RequiresPermission(Manifest.permission.SET_WALLPAPER)
public abstract void setWallpaper(Bitmap bitmap) throws IOException;

此例说明setWallpaper方法有设置壁纸的权限。

CallSuper Annotations


直接来了哈,我们看Activity.java源码里的onCreate方法

1
2
3
@CallSuper
protected void onCreate(Bundle savedInstanceState) {
}

@CallSuper说明所有重写onCreate()方法的方法都要有super.onCreate();

枚举注解


有时候,基于性能的考虑,需要用整型常量代替枚举类型,可以参考这篇文章:

胡凯 —— Android 性能优化典范 - 第3季

枚举注解,这就是大名鼎鼎的@IntDef and @StringDef,我们看看@IntDef源码

1
2
3
4
5
6
@Retention(Source)
@Target({ANNOTATION_TYPE})
public @interface IntRef {
long[] value() default {};
boolean flag() default false;
}

可见该注解表示不编译annotation到类文件中,用于注解类型,再来一发?好的,我们看看ActionBar源码吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import android.support.annotation.IntDef;
...
public abstract class ActionBar {
...
//Define the list of accepted constants
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})

//Tell the compiler not to store annotation data in the .class file
@Retention(RetentionPolicy.SOURCE)

//Declare the NavigationMode annotation
public @interface NavigationMode {}

//Declare the constants
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;

//Decorate the target methods with the annotation
@NavigationMode
public abstract int getNavigationMode();

//Attach the annotation
public abstract void setNavigationMode(@NavigationMode int mode);

我们来看,请忽略注释信息,前三句自定义了一个 @NavigationMode 注解,并使用 @IntDef 指定它可以接受的值类型。当使用setNavigationMode方法时,as会提示需要的参数,当然如果你写错的话,as会报错哦,so,as是一个神器。

大家还可以查看Toast源码,定义了一个@Duration的注解,makeText方法的第三个参数设置吐司时间长短的就用到了该注解,也就是时间必须是Toast.LENGTH_SHORT或Toast.LENGTH_LONG,如果你写的不是这两个,as会提示你的,比如,我这样写:

1
Toast.makeText(this, msg, 0).show();

AS 会在这里“0”附近出现提示,按 F1 后出现详情:

details

其实这个不影响运行,你点击run运行还是可以跑的,因为你run的时候没有运行 lint 检查,这个是可以设置的,会拖慢运行效率,参考这篇文章:

Android studio & lint 代码检查设置

那么这个提示处女座的朋友表示看着不爽,这个提示从哪里来的呢,其实这个是编译器效果,在 Setting 里可以找到:

desctiption

现在知道怎么回事了吧,一句话,as 编译器功能很强大,还有很多没有发现呢,so,如果你有更好的东东,请来这里分享下咯,哈哈

打造安卓开发航空母舰,Android Studio 使用集锦

当然@IntDef还可以定义标志位,详细说明请移步Improving Code Inspection with Annotations

好了,这里抛砖引玉,简单介绍了安卓注解,我们可以看到安卓源码里大量应用这个技巧,大家也要用起来哦,还可以来这里深入学习:
http://tools.android.com/tech-docs/support-annotations

安卓开源库收集整理中,欢迎 PR, star,地址:https://github.com/XXApple/AndroidLibs

分享是一种美德,更是一种生活方式!!

也许你会说我是一个梦想者,但我不是唯一的一个。

悦分享,越快乐^_^

欢迎交流,转载请注明出处,谢谢!

文章目錄
  1. 1. Annotation
  2. 2. Android Annotation
  3. 3. Nullness注解
  4. 4. 资源类型注解
  5. 5. 权限注解
  6. 6. CallSuper Annotations
  7. 7. 枚举注解
,
Fork me on GitHub