📎
|
反馈与建议,请移步: #2 |
文章更新历史:
-
2015/01/29 文章发布
-
2015/07/26 更新文章,解读新增的annotations
从Android Support Library v19.1开始,Support库新增了一个annotations子库。 这个库里面定义了一些annotation,可以被用于在代码中强制添加一些调用约束, 进而便于IDE对代码进行静态检查,以发现潜在的问题。
本文简单总结一下其用法。
直接修改build.gradle配置文件,添加该库的引用。例如:
dependencies { compile 'com.android.support:support-annotations:22.2.0' }
也可以通过Android Studio的Project Structure (File → Project Structure,Dependencies)添加引用。
📎
|
Annotations库并没有被上传到jcenter(其它Support库也是),
而是存放于Android SDK中的一个本地maven库中。
因此,如果需要在Java模块中使用Annotations库,则需要添加Support库的maven库:
maven { url '<your-SDK-path>/extras/android/m2repository' } 。
|
用于修饰Method的参数和返回值,以便IDE对相关的约束进行检查。列举如下:
-
@Nullable 表示允许为null
-
@NonNull 表示不允许为null
从官网抄一段例子:
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
...
@Nullable
@Override
public View onCreateView(String name, @NonNull Context context, @NonNull AttributeSet attrs) {
...
需要注意的是,对于一个变量或者返回值,除了可指定@NonNull和@Nullable之外, 还有第三种状态,即“未指定”。
|
当一个方法可能会返回null时,我们有两种选择: 一是指定@Nullable,二是什么都不指定。 如果打算指定为@Nullable,这意味着所有调用者都需要检查返回值是否为null。 也许,这并不是期望的行为,可能更好的选择是什么都不指定。 |
用于修饰对资源ID的相关引用,以便IDE对相关的资源类型进行检查。列举如下:
-
@AnimRes
-
@AnimatorRes
-
@AnyRes
-
@ArrayRes
-
@AttrRes
-
@BoolRes
-
@ColorRes
-
@DimenRes
-
@DrawableRes
-
@FractionRes
-
@IdRes
-
@IntegerRes
-
@InterpolatorRes
-
@LayoutRes
-
@MenuRes
-
@PluralsRes
-
@RawRes
-
@StringRes
-
@StyleRes
-
@StyleableRes
-
@XmlRes
从官网抄一段例子:
import android.support.annotation.StringRes;
...
public abstract void setTitle(@StringRes int resId);
我们经常使用int来定义一些常量来代替使用enum,可以使用这个annotation来添加相关的约束。
还是搬官网的例子:
import android.support.annotation.IntDef;
...
public abstract class ActionBar {
...
@Retention(RetentionPolicy.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;
@NavigationMode
public abstract int getNavigationMode();
public abstract void setNavigationMode(@NavigationMode int mode);
再搬一个例子,关于flags类型(可进行异或运算)的常量定义:
@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 {}
从Support库v22.2开始,加入了几个线程相关的annotations:
-
@MainThread 指定在主线程中执行
-
@UiThread 指定在UI线程中执行
-
@WorkerThread 指定在非UI线程中执行
-
@BinderThread 指定在Binder线程中执行
如果某个方法仅在某一类线程中调用,那么可以为其添加上面的annotation; 如果某个类的所有方法都仅在某一类线程中调用,那么可以为类添加线程annotation。
对于float或double类型的参数,可以使用@FloatRange来指定取值范围:
public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
对于int或long类型的参数,可以使用@IntRange来指定取值范围。
public void setAlpha(@IntRange(from=0,to=255) int alpha) {
如果允许一个方法被重写,但要求在子类的重写方法中调用基类的方法, 则可以使用@CallSuper:
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
@CheckResult 适用于必须使用返回值的场景。例如:
@CheckResult(suggest="#enforcePermission(String,int,int,String)")
public abstract int checkPermission(@NonNull String permission, int pid, int uid);