Android注解基础和自定义

在android的开发中注解使用是非常常见的,注解可以使代码阅读更加的清晰,整洁,可读性大大增强。
注解的原理:
使用interface来用作标记,@Target来用作描述类型(包括类、成员变量、方法等)@Retention来描述生命周期。其内部是通过类的反射机制,调用指定对象的方法,从而达到与对象直接调用方法相同的效果。

一、注解作用

在Java开发中,注解一般有以下功能:

标识

java SE5,在jdk中,类似我们比较常见的注解有Override,Deprecated,SuppressWarnings,这些作用只是作为标识,删除对程序没影响。他们的作用分别为:
Override 表示这个方法重写了父类的方法
Deprecated 表示jdk中不建议使用这个方法或者属性
SuppressWarnings 表示屏蔽了某些警告

java8 新特性:Repeatable 表示允许多次使用同一个注解

运行时处理

这个编译器默认的做法,编译器会通过class文件,逐个逐个的遍历class的属性和方法,即运行时处理。

编译时处理

在运行之前,有学过C的程序猿就会知道,编译器在运行之前,编译的时候会将include进来的*.h文件进行引入。同理例如你在代码中引入注解,编译器会在编译的时候,将注解的属性引入再进行编译。

二、注解基础

先看一个简单自定义注解

@Target(ElementType.TYPE)  //用于描述类
@Retention(RetentionPolicy.RUNTIME)  //运行时注解
public @interface ContentView {
    //注解的值
    int value();
}

这上面记得要添加一个@,不然就变成定义一个接口。在这里,value()不是代表一个方法,而是代表一个属性,其中value是属于整形的属性,默认值为1。
自定义的上面的@Target@Retention就是传说中的元注解,下面看下元注解

元注解 作用
@Target 表示该注解可以用于什么地方,可能在ElementType参数包括:
**CONSTRUCTOR: 用于描述构造器
FIELD: 用于描述域
LOCAL_VARIABLE: 用于描述局部变量
METHOD: 用于描述方法
PACKAGE: 用于描述包
PARAMETER: 用于描述参数
TYPE: **用于描述类、接口(包括注解类型) 或enum声明
@Retention 表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:
SOURCE: 注解将被编译器丢弃
CLASS: 注解在class文件中可用,但会被VM丢弃。
RUNTIME: VM将在运行期也保留注解,因此可以通过反射机制读取注解的信息
@Document 将此注解包含在javadoc中
@Inhrited 允许子类继承父类中的注解

java 8新特性:java 8之前注解只能是在声明的地方所使用,比如类,方法,属性;java 8里面,注解可以应用在任何地方,比如方法参数前面等。

三、自定义注解的格式

public @interface 注解名{注解体}。注解体中注解元素可以被public修饰,也可以什么也不写,元素类型可以是:

  1. 所有基本数据类型(int,float,boolean等八种基本类型)
  2. String类型
  3. Class类型
  4. enum类型
  5. Annotation类型(说明注解可以嵌套)
  6. 以上所有类型的数组

默认值的限定

编译器对默认值过分的挑剔,要么有确定的默认值,要么在使用的时候提供元素的值。
基本类型的元素都有默认值,不用写default也可以,但是想String这类就必须要写,而且不能写null,因此在某些需要分清是null还是空字符串的地方要注意。

四、自定义注解

注解声明:

@Target(ElementType.TYPE)  //用于描述类
@Retention(RetentionPolicy.RUNTIME)  //运行时注解
public @interface ContentView {
    //注解的值,默认为1,可不写
    int value() default 1;
}

标记类:

@ContentView(R.layout.activity_main)
public class DemoActivity extends AppCompatActivity {

    @FindView(R.id.btn1)
    private AppCompatButton mBtn1;

    @FindView(R.id.btn2)
    private AppCompatButton mBtn2;

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

injectContentView(this)负责将值注入:

/**
     * 通过反射将值注入
     *
     * @param activity
     */
    private void injectContentView(Activity activity) {
        //获取activity对应的class
        Class a = activity.getClass();
        //判断当前class是否有ContentView的注解
        if (a.isAnnotationPresent(ContentView.class)) {
            //获取注解实例
            ContentView contentView = (ContentView) a.getAnnotation(ContentView.class);
            //获取注解中的值
            int layoutIt = contentView.value();
            try { //获取class的方法,第一个参数是方法名,第二个是方法参数的类型
                Method method = a.getMethod("setContentView", int.class);
                method.setAccessible(true);
                //调用指定对象的此方法,第二个是方法的参数
                method.invoke(activity, layoutIt);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
    }

这里就只是简单的介绍了注解!还有好多东西后面慢慢写

你可能感兴趣的:(Android注解基础和自定义)