Android中Annotation的使用详解

都说Annotation的运用非常简单,但真正我们需要下手实现的的时候,有的时候就不知道从哪里下手,为什么我们觉得很简单的东西,但却无法下手呢?
原因只有一个,我们对它的使用非常少,但对于写框架的人来说Annotation却使用的频率非常高。那既然我们平时用的非常少,我写这篇blog就没什么意义了,的确,那我也只当是给大家做个查阅的文档。不过我还是希望大家能通过这篇blog,加强对Annotation的理解,这篇blog省去了Annotation不必要的知识点,就像慕课网所说的只学有用的。
进入主题:
一、先分析源码:
只需要知道一下四个类就行了
1、

  @Documented
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.ANNOTATION_TYPE)
  public @interface Retention {
      RetentionPolicy value();
  }

这个注解的作用是当我们需要声明自定义的Annotation是,需要用到此注解,还需要设置value的值;value的值的作用,就需要讲第二个类的时候说明,使用方法,可以参考此类本身,直接在自定义的Annotation上加上@Retention(RetentionPolicy.RUNTIME),或者另一种写法@Retention(value = RetentionPolicy.RUNTIME),效果是一样的,这里需要注意一点的是,Annotation可以用自己来对自己进行注解说明。
2、

  public enum RetentionPolicy {
      /**
       * Annotation is only available in the source code.
       */
      SOURCE,
      /**
       * Annotation is available in the source code and in the class file, but not
       * at runtime. This is the default policy.
       */
      CLASS,
      /**
       * Annotation is available in the source code, the class file and is
       * available at runtime.
       */
      RUNTIME
  }

这个是一个枚举类型,功能是控制Annotation的级别,值越大,权限越高,Annotation的作用范围越大,下面分别解释三个级别的作用范围:
SOURCE:只在源文件此注解中有效,也就是,只要代码已经编译过了,权限被声明为SOURCE的Annotation就无效;
CLASS: 文件或者代码已经编译了,这个时候还有效,当代码跑起来了的时候,就没有效果了;
RUNTIME:这个相当于最大权限,记住可用于任何时候,而我们在写代码的时候,都是希望在运行时候用,所以,一般情况下我们都是声明为RUNTIME权限。

3、

  @Documented
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.ANNOTATION_TYPE)
  public @interface Target {
      ElementType[] value();
  }

这又是一个注解类,这个类的作用也是在我们自定义Annotation的时候声明,然后确定自定义Annotation的作用类型是那个地方,它的取值就是下一个类所要讲的,用法与Retention注解一样,确切的说所有的Annotation都是这样使用
4、

public enum ElementType {
      /**
       * Class, interface or enum declaration.
       */
      TYPE,
      /**
       * Field declaration.
       */
      FIELD,
      /**
       * Method declaration.
       */
      METHOD,
      /**
       * Parameter declaration.
       */
      PARAMETER,
      /**
       * Constructor declaration.
       */
      CONSTRUCTOR,
      /**
       * Local variable declaration.
       */
      LOCAL_VARIABLE,
      /**
       * Annotation type declaration.
       */
      ANNOTATION_TYPE,
      /**
       * Package declaration.
       */
      PACKAGE
  }

这个类就是确定Annotation的作用位置,每个不同的值,对应的位置不相同

/**
* 作用于类,接口或枚举
*/
TYPE,
/**
* 作用于字段,也就是成员变量.
*/
FIELD,
/**
* 作用于方法.
*/
METHOD,
/**
* 参数.
*/
PARAMETER,
/**
* 构造方法.
*/
CONSTRUCTOR,
/**
* 本地变量.
*/
LOCAL_VARIABLE,
/**
* 注解.
*/
ANNOTATION_TYPE,
/**
* 包名.
*/
PACKAGE

我只是把英文翻译了一遍,如果有错请指正。
基本用法介绍完了,接下来开始自定义Annotation
二、自定义Annotation
通过Android studio创建Annotation类,创建类的时候可以直接指定Annotation类型,这样创建出来的文件如下:

 /**
   * Created by moon.zhong on 2015/2/14.
   */
  public @interface TestAnnotation {
  }

和接口非常像,只不过多了一个@,根据刚刚所讲,需要再类上加上@Retention(RetentionPolicy.RUNTIME)来确定权限的大小,这里直接采用最大权限,并指定作用的类型@Target(ElementType.METHOD),这里指定作用于方法上面
自定义Annotation就完成了。

三、使用Annotation
写任何代码都不是用来看的,所以我们一定得知道如何使用它。
Annotation往往是跟反射结合起来使用的,我们在学习反思的时候,知道反射里面很多方法获取Annotation的值,也可以得出这样一个结论,用到了Annotation的情况下,基本上就用到了反射,我们常说的一句话,无反射,不框架,这也是为什么但大部分框架都大量使用Annotation的原因
这里也是用反射的列子来说明Annotation的使用
编写好自定义的Annotation,让其作用范围在类上面,

/**
* Created by moon.zhong on 2015/2/14.
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
public @interface ClassAnnotation {
}
定义好一个Bean的类,加上注解

  /**
   * Created by moon.zhong on 2015/2/14.
   */
  @ClassAnnotation
  public class Bean {
  }
 //通过反射来查看注解是否已经能正常使用

  public class MainActivity extends ActionBarActivity {

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          Class mClass = Bean.class ;
          Annotation annotation[] = mClass.getAnnotations() ;
          for (Annotation a : annotation){
              Log.v("zgy","====getAnnotations===="+a.annotationType()) ;
          }
      }
  }

最后打印的log信息:zgy﹕ ====getAnnotations====interface moon.annotationdemo.ClassAnnotation

再来看看怎么给自定义的Annotation设置值,像@Retention(RetentionPolicy.RUNTIME)一样后面可以跟上一个值。在上面看log信息的时候,你是否发现了多打印了一个interface,而后面紧跟着的才是Annotation的全名,其实Annotation本省就是接口的一种,所以在声明变量的时候,只需定义一个抽象方法即可,不需要实现,完全可以参照 public @interface Retention

  /**
   * Created by moon.zhong on 2015/2/14.
   */
  @Retention(value = RetentionPolicy.RUNTIME)
  @Target(value = ElementType.TYPE)
  public @interface ClassAnnotation {
      String print() ;
  }www.2cto.com

  /**
   * Created by moon.zhong on 2015/2/14.
   */
  @ClassAnnotation(print = "annotation")
  public class Bean {
  }

使用也是一样的同 @interface Retention ,在Bean的类名上面加上@ClassAnnotation(print = “annotation”),这里有一点需要注意,不能写成@ClassAnnotation(“annotation”),因为这里定义的方法是print(),如果换成value() 就可以省略。

    /**
     * Created by moon.zhong on 2015/2/14.
     */
    @Retention(value = RetentionPolicy.RUNTIME)
    @Target(value = ElementType.TYPE)
    public @interface ClassAnnotation {
        String value() ;
    }

    /**
     * Created by moon.zhong on 2015/2/14.
     */
    @ClassAnnotation("annotation")
    public class Bean {
    }

来测试下:
for (Annotation a : annotation){
Log.v(“zgy”,”====print====”+((ClassAnnotation)a).print()) ;
}

打印log的信息 zgy﹕ ====print====annotation
说明我们已经拿到了所设置的值,那么接下来要实现什么要的功能就看大家的智慧了。
四、总结:
老规矩,就像烧菜最后都要浇汁,这里来做个总结,在定义Annotation的时候,需要注意两点,一、通过@Retention(RetentionPolicy.RUNTIME)注解来确定声明的Annotation的作用权限,这里一般设为最大就可以了;二、通过@Target(ElementType.ANNOTATION_TYPE)注解来确定此注解的作用对象是谁。还有一点需要注意,自定义的Annotation如果定义了抽象方法,如果抽象方法名为value的时候,使用的时候可以省略,其他时候不能省略,个人建议,都加上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值