Support Annotation 小结

Support Annotation 是指 Andoid Support Library 从 19.1 开始引入的注解库,通过compile 'com.android.support:support-annotations:22.2.0'就能引入。它可以检验代码潜在的问题并提醒你去修正它。
下面简单介绍下我常用的几个注解,更加全面的介绍可以看官方文档

Nullable & NonNull

作为 Android 开发者,看到NullPointer就五味杂成。当它发生时要么后悔这里咋不小心没写个判断,要么就是咒骂这里返回的值怎么可以是Null
如果你碰到这样的情况很多,那么这两个注解就是为你而服务的。
Nullable表明这里的值可能会空,而NonNull则表示这里的值必须不为空。两者可以使用在MethodPamameter以及Field上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.tv);
// Method invocation 'getContent().getLength() may produce 'java.lang.NullPointerException'
tv.setText("The length of content is " + getContent().length());
}

@Nullable
private String getContent() {
return null;
}

}

举个例子,当你使用Nullable标注的方法并对返回值不加判断直接使用时,IDE 就会高亮有问题的语句,如上段代码中的getContent().length(),并提醒你这里可能会出现NullPointerException

IntDef & StringDef

处于性能的考虑,在 Android 开发中我们会使用Int常量来代替Enum类型,而Int常量缺乏像Enum的类型安全性。但我们可以通过IntDef来达到类似Enum的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import android.support.annotation.IntDef;
...
public abstract class ActionBar {
...
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
@Retention(RetentionPolicy.SOURCE)
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;

@NavigationMode
public abstract int getNavigationMode();

public abstract void setNavigationMode(@NavigationMode int mode);

若我们在setNavigationMode中传入错误的参数,如3,则 IDE 就会报错,并提示可以使用的值。
IntDef还有个高级属性flag,当设置为true时就可以通过 & 或 | 进行位操作,类似于EnumSet的相关操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import android.support.annotation.IntDef;
...

@IntDef(flag=true, value={
DISPLAY_USE_LOGO,
DISPLAY_SHOW_HOME,
DISPLAY_HOME_AS_UP,
DISPLAY_SHOW_TITLE,
DISPLAY_SHOW_CUSTOM
})
@Retention(RetentionPolicy.SOURCE)
public @interface DisplayOptions {}

public static final int DISPLAY_USE_LOGO = 0x1;
public static final int DISPLAY_SHOW_HOME = 0x2;
public static final int DISPLAY_HOME_AS_UP = 0x4;
public static final int DISPLAY_SHOW_TITLE = 0x8;
public static final int DISPLAY_SHOW_CUSTOM = 0x10;

public abstract void setDisplayOptions(@DisplayOptions int options);

// 使用
getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE);

Thread Annotations

Support Library 在 22.2 之后又引入了 Thread Annotations,用来标注方法所需要的线程环境。如果一个类中的所有方法对线程环境的要求都相同,则可以来标注整个类。
Thread Annotations 有以下4种,其中 UiThread 和 MainThread 没有本质区别,可以互换。

  • @UiThread
  • @MainThread
  • @WorkerThread
  • @BinderThread
    使用效果如下图所示。

Resource Type Annotations

Android 中通过 id 来获取相应的资源文件,但由于 id 都是 int 型,不同类型的资源文件无法区别,在使用中可能会传入错误类型的 id。而通过 Resource Type Annotations 就可以避免这种错误。
如 ActionBar 中 setTitle 方法,若传入 setTitle(R.drawable.title) 就会报错。

1
public abstract void setTitle(@StringRes int resId);

Resource Type Annotations 主要有以下几种:

  • @StringRes
  • @DrawableRes
  • @ColorRes
  • @InterpolatorRes
    除了特定类型的 Annotation,还有一种不指定资源类型的注解 @AnyRes。在不确定是哪种类型资源的情况下使用,如 Resources#getResourceName(@AnyRes int resId)

除了上面介绍的,还有 RGB Color Integers、Permission、Value Constraints 等相关的 Annotations,可参考官方文档进行学习。

参考