美文网首页Android基础
Android注解基础和自定义

Android注解基础和自定义

作者: Candy有雪吃 | 来源:发表于2018-08-08 17:36 被阅读7次

    在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注解基础和自定义

        本文链接:https://www.haomeiwen.com/subject/fskxbftx.html