Android中注解(Support Annotations)的使用

简介

注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明。善用注解可提高您的代码质量和效率。

JDK自带的注解

@Override-----------------------表示当前方法覆盖了父类的方法

@Deprecated-------------------表示方法已经过时,方法上有横线,使用时会有警告。

@SuppressWarnings-------表示关闭一些警告信息(通知java编译器忽略特定的编译警告)

下面我们进行一个示例来演示这3种注解的使用

定义一个Animal的抽象类,包括3个方法,其中eat()方法设置为过时的,方法头加上@Deprecated:

public abstract class Animal {
    privatestatic final String TAG = Animal.class.getSimpleName();
 
    /**
     * eat
     *@deprecated Use {@link #feed()}
     */
    @Deprecated
    public void eat() {
        feed();
    }
 
    /**
     * feed
     */
    public void feed() {
       Log.e(TAG, "feed");
    }
 
    /**
     * sleep
     */
    public voids leep() {
       Log.e(TAG, "sleep");
    }
}

新建一个Pig的类,使继承于Animal,因为它重写了sleep()方法,所以在其方法上加上@Override:

public class Pig extends Animal {
 
    privatestatic final String TAG = Pig.class.getSimpleName();
 
    @Override
    public voidsleep() {
       Log.e(TAG, "sleep");
    }
}

假设,我们在一个叫test()的方法中实例化一个Pig对象,然后分别调用它的eat()、feed()和sleep()方法:

private void test() {
    Animal pig= new Pig();
    pig.eat();
    pig.feed();
   pig.sleep();
}

可以在你的IDE中看到调用pig.eat();的代码是被加上了划线的,这是一个代码的警告,因为我们之前把eat()方法设置为过时的,若此时想不显示此警告,可以在test()方法上加入@SuppressWarnings("deprecation"),如:

@SuppressWarnings("deprecation")
private void test() {
    Animal pig= new Pig();
    pig.eat();
    pig.feed();
   pig.sleep();
}

这里说明一下,@SuppressWarnings注解接收一个字符串参数,其参数含义是:

@SuppressWarnings("unchecked")--------------未检查的转化,如集合没有指定类型

@SuppressWarnings("unused")--------------------未使用的变量

@SuppressWarnings("resource")------------------有泛型未指定类型

@SuppressWarnings("path")-------------------------在类路径,原文件路径中有不存在的路径

@SuppressWarnings("deprecation")------------使用了某些不赞成使用的类和方法

@SuppressWarnings("fallthrough")--------------switch语句执行到底没有break关键字

@SuppressWarnings("serial")------------------------某类实现Serializable 但是没有定义serialVersionUID这个需要但是不必须的字段

@SuppressWarnings("rawtypes")-----------------没有传递带有泛型的参数

@SuppressWarnings("all") ----------------------------全部类型的警告

 

Android中的注解

除了Java JDK自带的3种注解外,Android中也有相应类型的注解,分别是Nullness注解、资源注解、线程注解、值约束注解、权限注解、返回值注解、CallSuper注解、Typedef 注解、代码可访问性注解,等。下面看看这些注解的是如何使用的

Nullness注解

Nullness注解有:@Nullable@NonNull。它们是用于检查给定变量、参数或返回值是否为null的情况。@Nullable指示可以为null,而@NonNull则指示不可为null。

示例:

public class Person {
    @NonNull
    privateString mName;
 
    @Nullable
    publicString getName() {
        returnmName;
    }
 
    public voidsetName(@NonNull String name) {
        mName =name;
    }
}

在Person类中全局变量mName和方法setName()的参数都标注为不可为空,而getName()方法标注为返回参数可为空,接着再来看看错误的调用代码:

@NonNull
private String mMyName;
……
Person person = new Person();
// 下面三行代码是一个错误的演示,都会被IDE给出相应的警告
mMyName = null;                               
person.setName(null);
mMyName = person.getName();

资源注解

资源注解有:@StringRes@DrawableRes@DimenRes@ColorRes@InterpolatorRes、@LayoutRes。等。因为 Android 对资源的引用以整型形式传递,所以它们的作用是用于检查参数资源类型是否合法。其中,如果您的参数支持多种资源类型,您可以在给定参数上添加多个注解。使用@AnyRes能够指示注解的参数可为任意类型的R资源。

示例:

void setColor(@ColorRes int color) {
    // ...
}

调用:

setColor(R.string.app_name);         // 错误的调用
setColor(R.color.colorWhite);          // 正确的调用

在使用@ColorRes指定参数应为颜色资源后,若颜色整型(RRGGBB 或 AARRGGBB 格式)仍然是无法识别为颜色资源。这种情况,请改用 @ColorInt 注解指示参数必须为颜色整型。

示例:

void setColor2(@ColorInt int color) {
    // ...
}

调用:

setColor2(R.color.colorWhite);        // 错误的调用
setColor2(0x80F6F6F6);                // 正确的调用

线程注解

线程注解有:@MainThread@UiThread@WorkerThread@BinderThread@AnyThread。它们用于检查某个方法是否从特定类型的线程调用。其中,构建工具会将 @MainThread 和 @UiThread 注解视为可互换,因此,您可以从 @MainThread 方法调用 @UiThread 方法,反之亦然。

值约束注解

值约束注解有:@IntRange@FloatRange@Size 。它们用于验证传递的参数的值的取值范围或长度。

示例:

public void setAlpha(@IntRange(from=0, to=255) intalpha) {
    // ...
}
public void setAlpha(@FloatRange(from=0.0, to=1.0)float alpha) {
    // ...
}
public void setLocation(@Size(min=1) int[]location) {
    // ...
}
public void setLocation2(@Size(max=2) int[]location){
    // ...
}
public void setLocation3(@Size(3) int[]location) {
    // ...
}

这里说下@Size注解,它是可以检查集合或数组的大小,以及字符串的长度,上面示例中,setLocationset的传入参数指定数组要求最小大小为1;而setLocationset2则指定要求最大大小为2;最后setLocation3是指定要求确切大小为3。

权限注解

使用@RequiresPermission注解可以验证方法调用方的权限。要检查有效权限列表中是否存在某个权限,请使用anyOf 属性。要检查是否存在一组权限,请使用allOf 属性。

示例1,若要调用setWallpaper()方法,要确保方法的调用方拥有permission.SET_WALLPAPERS权限:

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

示例2,若要调用copyFile()方法,要确保调用方同时具有外部存储空间的读写权限:

@RequiresPermission(allOf = {
   Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.WRITE_EXTERNAL_STORAGE})
public static final void copyFile(String dest, Stringsource) {
    ...
}

示例3,intent权限的检查:

public void startMyActivity(@RequiresPermissionIntent intent) {
   startActivity(intent);
}

调用:

Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:123456789"));
startMyActivity(intent);

这时,若调用方没有打电话权限,则IDE会有警告:Missing permissions required by intentIntent.ACTION_CALL:android.permsiion.CALL_PHONE

示例4,若需要单独读写权限的内容提供程序的权限,可使用:@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");

返回值注解

返回值注解:@CheckResult可以验证实际使用的是方法的结果还是返回值。该注解意味着需要调用方对方法的返回值进行处理

示例:

@CheckResult
public boolean checkValid(String value) {
    returnTextUtils.isEmpty(value);
}

调用:

checkValid("");                                // 错误的调用,因为调用方法后返回的值没有对其作处理
boolean check = checkValid("");                // 正确的调用

CallSuper注解

@CallSuper注解可以验证子类中重写父类的方法一定需要同时调用父类实现,即要求子类调用super.XX()。

示例:

// 父类代码:
public abstract class Animal {
    @CallSuper
    public voidsleep() {
    }
}
// 子类代码,若不调用super.sleep();,则IDE会给出警告:Overriding method should callsuper.sleep
public class Pig extends Animal {
    @Override
    public voidsleep() {
//       super.sleep();
    }
}

Typedef 注解

Typedef注解,有些人会叫它枚举注解,因为它的作用跟枚举类似。Typedef 注解可以确保特定参数、返回值或字段引用特定的常量集。它们还可以完成代码以自动提供允许的常量。

Typedef 注解使用@interface声明新的枚举注解类型。@IntDef@StringDef注解以及@Retention可以标注新注解,并且为定义枚举的类型所必需。@Retention(RetentionPolicy.SOURCE) 注解可以告知编译器不将枚举的注解数据存储在.class文件中。

示例1:

public static final int LENGTH_LONG = 1;
public static final int LENGTH_SHORT = 0;
@IntDef({LENGTH_SHORT, LENGTH_LONG})
@Retention(RetentionPolicy.SOURCE)
public @interface Duration {}
 
public void setDuration(@Duration int duration) {
    //mDuration = duration;
}
 
@Duration
public int getDuration() {
    returnLENGTH_LONG;
}

上面示例,其实是Toast的部分源码,我们在设置Toast显示时间时,只能设置两个值:LENGTH_LONG 和 LENGTH_SHORT就是这样做到的

示例2:

@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 {
    // ...
}

@IntDef注解中,还可以指定flag的值(若不指定则为false),如果我们将flag设为true,则表示可以将允许常量与标志(例如,|、& 和 ^,等等)相结合

代码可访问性注解

@Keep注解用于标注类或方法在混淆的时候将不会被混淆

其他常见的注解

@TargetApi注解用于屏蔽IDE提示要求某一新API版本的错误

示例,一段代码要求Android5.0才行效,但我们又明确知道非Android5.0的情况不会调用到该段代码:

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void test() {
    // ...
}

@SuppressLint注解跟@TargetApi注解类似,不同的是@SuppressLint注解用于屏蔽IDE提示要求的一切API版本的错误,注意是一切

@Widget注解用于表示该类是自定义的Widget类

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值