Android Support Annotation介绍

在浏览Butter Knife源码时,发现里面用了好几个support包里的注解,比如@UiThread;当时一脸懵逼,第一次见到。再学习过后,今天,介绍下support包的注解。注解可以简化代码并提高编码的效率,所以熟练使用support包里的注解还是很有必要的。

对注解还不太了解的盆友,可以看看这篇博客深入理解Java注解类型

Nullness注解

@Nullable@NonNull

这两个注解都是标记注释,没有特定的属性。

@Nullable用在参数,字段或方法的返回值上,表示可以为null;

 @Override
 public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mHitMvpPresenter.attachView(this);
        initPresenter(mHitMvpPresenter);
        mMovieListAdapter.setBaseFragment(this);
 }

FragmentonCreate()中,@Nullable用在savedInstanceState上表示可以传入null进去。

@NonNull用在参数,字段或方法返回值上,表示不能为空。

在调用某个方法时,方法参数上有@Nullable,就表示可以给个null,而不必担心空指针;方法参数上有@NonNull,就表示不可以给null,否则会出现空指针。这样就可以提高编码效率,避免不必要的错误。

资源注解

资源注解也都是标记注释,没有特定的属性。

@AnimatorRes用在整数参数、字段或方法返回值上,表示动画资源

@AnimRes用在整数参数、字段或方法的返回值上,表示anim资源

@AnyRes用在整型参数、字段或方法返回值上,表示任何类型的资源

@ArrayRes用在整数参数,字段或方法的返回值上,表示数组资源

@AttrRes用在整数参数,字段或方法的返回值上,表示属性资源(R.attr.height

@BoolRes用在整数参数,字段或方法的返回值上,表示布尔资源

@ColorRes用在整数参数,字段或方法的返回值上,表示颜色资源

@DimenRes用在整数参数,字段或方法的返回值上,表示dimen资源(R.dimen.bar_height

@DrawableRes用在整数参数,字段或方法的返回值上,表示drawable资源

@FontRes用在整数参数,字段或方法的返回值上,表示字体资源(R.font.myfont

@FractionRes用在整数参数,字段或方法的返回值上,表示百分数资源(R.fraction.test

@IdRes用在整数参数,字段或方法的返回值上,表示id资源(R.id.button

@IntegerRes用在整数参数,字段或方法的返回值上,表示integer资源(android.R.integer.config_shortAnimTime

@InterpolatorRes用在整数参数,字段或方法的返回值上,表示插值器资源(android.R.interpolator.cycle)。

@LayoutRes用在整数参数,字段或方法的返回值上,表示布局文件资源

@MenuRes用在整数参数,字段或方法的返回值上,表示菜单资源

@NavigationRes用在整数参数,字段或方法的返回值上,表示导航资源(R.navigation.flow

@PluralsRes用在整数参数,字段或方法的返回值上,表示plurals资源(复数形式的字符串,具体可以参考这篇博客)

@RawRes用在整数参数,字段或方法的返回值上,表示raw资源

@StringRes用在整数参数,字段或方法的返回值上,表示字符串资源

@StyleableRes用在整数参数,字段或方法的返回值上,表示自定义属性资源(android.R.styleable.TextView_text

@StyleRes用在整数参数,字段或方法的返回值上,表示样式资源

@TransitionRes用在整数参数,字段或方法的返回值上,表示过渡资源(Activity之间切换时的过渡动画)

@XmlRes用在整数参数,字段或方法的返回值上,表示xml资源

用的最多的就是@StringRes@ColorRes@DimenRes@IdRes@DrawableRes;以@DrawableRes为例

public void setBackground(int id){
    imageView.setBackgroundResource(id);
}

public void setBackgroundRes(@DrawableRes int id){
    imageView.setBackgroundResource(id);
}

给这两个方法都传入非drawable资源id,比如0;编译的时候,setBackgroundRes()
就会报错;而setBackground()能编译通过,但是在运行的时候程序就会崩溃。setBackground()发现错误比setBackgroundRes()晚,如果setBackground()也用@DrawableRes的话,就可以在编译阶段发现错误。在这例子中,资源注解就是帮助编译器在编译阶段检查方法参数是否是资源id。

值约束注解

@FloatRange@IntRange@Size@ColorInt@ColorLong@HalfFloat@Dimension@Px

@IntRange表示元素在给定的int或long范围内

@Retention(CLASS)
@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE})
public @interface IntRange {
    /** Smallest value, inclusive */
    long from() default Long.MIN_VALUE;
    /** Largest value, inclusive */
    long to() default Long.MAX_VALUE;
}

当不知道一个注解可以用在什么元素上时,可以点开它;看看它的@Target内容。在这,@IntRange可以用在方法、方法参数、字段、局部变量、注解上。当未指定Target值时,此注解就可以用于任何元素之上。

有两个属性,而且都有默认值。

public void setColor(@IntRange(from=0,to=255) int color) {
    .....
}

@FloatRange表示元素在给定的float或double范围内,用法与@IntRange一样。

@Retention(CLASS)
@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE})
public @interface FloatRange {
    /** Smallest value. Whether it is inclusive or not is determined
     * by {@link #fromInclusive} */
    double from() default Double.NEGATIVE_INFINITY;
    /** Largest value. Whether it is inclusive or not is determined
     * by {@link #toInclusive} */
    double to() default Double.POSITIVE_INFINITY;

    /** Whether the from value is included in the range */
    boolean fromInclusive() default true;

    /** Whether the to value is included in the range */
    boolean toInclusive() default true;
}

@IntRange多了两个方法;fromInclusive()表示是否包含from值,默认是包含的;toInclusive()表示是否包含to值,默认是包含的。@FloatRange可以通过这两个方法来控制是否包含from值与to值;而@IntRange是默认包含的,不能改变。

@Size表示元素具有的给定的大小或长度。

@Retention(CLASS)
@Target({PARAMETER,LOCAL_VARIABLE,METHOD,FIELD,ANNOTATION_TYPE})
public @interface Size {
    /** An exact size (or -1 if not specified) */
    long value() default -1;
    /** A minimum size, inclusive */
    long min() default Long.MIN_VALUE;
    /** A maximum size, inclusive */
    long max() default Long.MAX_VALUE;
    /** The size must be a multiple of this factor */
    long multiple() default 1;
}

min()表示最小的大小( @Size(min=1))

max()表示最大的大小(@Size(max=5))

value()表示确定的大小(@Size(value=3)或@Size(3))

multiple()表示大小必须为此数字的倍数(@Size(multiple=2))

@ColorInt表示元素为颜色的int值,以Color类文件中BLACK的声明为例。

@ColorInt public static final int BLACK = 0xFF000000;

@ColorLong表示元素为颜色的long值,@ColorInt比它更常用一些。

@HalfFloat表示元素为半精度浮点数。(半精度浮点数是IEEE754标准的浮点数类型之一,精度为0.001,占2字节空间;适用于对精度要求不高,但对存储空间要求很高的场合)。比如在Color类文件中的pack()就用到了该注解。

@ColorLong
public static long pack(float red, float green, float blue, float alpha,@NonNull ColorSpace colorSpace) {
        ..........

        @HalfFloat short r = Half.toHalf(red);
        @HalfFloat short g = Half.toHalf(green);
        @HalfFloat short b = Half.toHalf(blue);

        ..........
}

@Dimension表示整数参数,字段或方法的返回值是尺寸大小。

@Documented
@Retention(CLASS)
@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE})
public @interface Dimension {
    @DimensionUnit
    int unit() default PX;

    int DP = 0;
    int PX = 1;
    int SP = 2;
}

默认的单位是像素,可以通过unit()来修改。(@Dimension(uint=Dimension.DP)

@Px表示整数参数,字段或方法返回值是像素大小。

@Documented
@Retention(CLASS)
@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE})
@Dimension(unit = Dimension.PX)
public @interface Px {
}

@Dimension是可以用在注解声明上的,所以你也可以模仿@Px,自定义一个表示字体大小的注解。

@Documented
@Retention(CLASS)
@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE})
@Dimension(unit = Dimension.SP)
public @interface Sp {
}

Requires 注解

@RequiresApi@RequiresPermission

@RequiresApi表示元素只应在给定的API级别或更高级别上调用。

@RequiresPermission表示元素需要(或可能需要)一个或多个权限。

@Retention(CLASS)
@Target({ANNOTATION_TYPE,METHOD,CONSTRUCTOR,FIELD,PARAMETER})
public @interface RequiresPermission {

    String value() default "";

    String[] allOf() default {};

    String[] anyOf() default {};

    boolean conditional() default false;

    @Target({FIELD, METHOD, PARAMETER})
    @interface Read {
        RequiresPermission value() default @RequiresPermission;
    }

    @Target({FIELD, METHOD, PARAMETER})
    @interface Write {
        RequiresPermission value() default @RequiresPermission;
    }
}

value()表示只需要一个权限

allOf()表示需要多个权限

anyOf()表示至少需要一个权限

conditional()默认为false;如果为true,表示在某些情况下,可能不需要权限。

@RequiresPermission.Read表示为元素提供单独的相关读权限。

@RequiresPermission.Write表示为元素提供单独的相关写权限。

@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");

线程注解

@AnyThread表示元素可以被任何线程都调用

@BinderThread表示元素只能被Binder线程都调用

@MainThread表示元素只能被Main线程都调用

@WorkerThread表示元素只能被后台线程都调用

@UiThread表示元素只能被Ui线程都调用

构建工具会将 @MainThread@UiThread 注解视为可互换,因此,可以从 @MainThread 方法调用 @UiThread 方法,反之也一样。但是,MainThreadUiThread是有区别的;最好还是用 @UiThread 标注与应用的视图层次结构关联的方法,用 @MainThread 标注与应用生命周期关联的方法。

线程注解仅仅是提示编程者注解元素应该在那个线程里调用;在程序编译的时候,编译器没有检查注解元素是否在正确的线程里调用。比如下图中的用法,编译正常通过了,也没有警告或错误。
Android Support Annotation介绍_第1张图片

其他注解

@IntDef@StringDef

都只能用在注解的声明上,它们的作用类似于枚举,以@IntDef为例。

@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);

再调用setNavigationMode()时,其参数只能是上面这三个常量之一。

@CallSuper

只用在方法上,表示任何重写该方法的子类,也应该调用该方法。

 @Override
 protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        .......
}

如果注释掉super.onCreate(savedInstanceState);,就会出现下图中的情况。

这里写图片描述

编辑器是怎么知道的,就是因为@CallSuper;Activity的onCreate() 用到了这个注解。

Android Support Annotation介绍_第2张图片

@CheckResult

用来验证是否使用了方法返回值,可以通过添加注释来进行提示。

Android Support Annotation介绍_第3张图片

@GuardedBy

表示仅当持有了引用锁时,才能访问注释的方法或字段。

final Object objectLock = new Object();

@GuardedBy("objectLock")
volatile Object object;

Object getObject() {
      synchronized (objectLock) {
          if (object == null) {
              object = new Object();
          }
      }
   return object;
}

@Keep

用在包、类、注解、构造器、方法、字段上,表示在删除无用代码(应该就是代码混淆)时,会保留用了该注解的元素。

@RestrictTo

表示元素只应在特定范围内(RestrictTo.Scope)使用,具体参考官方文档。

@VisibleForTesting

表示一个代码块的可见性是否高于让代码变得可测试所需要的水平,具体参考官方文档

你可能感兴趣的:(Android)