注解和反射

注解

定义数据

companion object {
        const val RESOUCES_ONE = 1;
        const val RESOUCES_TWO = 2;
    }

定义数据

@IntDef({MainActivity.RESOUCES_ONE,MainActivity.RESOUCES_TWO})
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.SOURCE)
public @interface AnnotateValue {
}

输入错误会提示

错误提示

下面解释

@Target:注解的作用目标

public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE,

    /**
     * Module declaration.
     *
     * @since 9
     */
    MODULE
}
参数 原文 注解
ElementType.TYPE Class, interface (including annotation type), or enum declaration 类、接口(包括注释类型)或枚举声明
ElementType.FIELD Field declaration (includes enum constants) 字段声明(包括枚举常量)
ElementType.METHOD Method declaration 方法声明
ElementType.PARAMETER Formal parameter declaration 形式参数声明
ElementType.CONSTRUCTOR Constructor declaration 构造函数声明
ElementType.LOCAL_VARIABLE Local variable declaration 局部变量声明
ElementType.ANNOTATION_TYPE Annotation type declaration 注解类型声明
ElementType.PACKAGE Package declaration 包装声明
ElementType.TYPE_PARAMETER Type parameter declarationSince:1.8 类型参数声明自从:1.8
ElementType.TYPE_USE Use of a type Since:1.8 使用类型自从:1.8
ElementType.MODULE Module declaration. Since:9 模块声明。自从:9
  @Target(ElementType.TYPE)——接口、类、枚举、注解
  @Target(ElementType.FIELD)——字段、枚举的常量
  @Target(ElementType.METHOD)——方法
  @Target(ElementType.PARAMETER)——方法参数
  @Target(ElementType.CONSTRUCTOR) ——构造函数
  @Target(ElementType.LOCAL_VARIABLE)——局部变量
  @Target(ElementType.ANNOTATION_TYPE)——注解
  @Target(ElementType.PACKAGE)——包

@Retention:注解的保留位置

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}
参数 原文 注解
RetentionPolicy.SOURCE Annotations are to be discarded by the compiler. 注释将被编译器丢弃。
RetentionPolicy.CLASS Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time. This is the default behavior. 注释将由编译器记录在类文件中,但不需要在运行时由 VM 保留。 这是默认行为。
RetentionPolicy.RUNTIME Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.See Also:reflect.AnnotatedElement 注释将由编译器记录在类文件中,并在运行时由 VM 保留,因此可以反射性地读取它们。反射.AnnotatedElement

RetentionPolicy.SOURCE:这种类型的Annotations只在源代码级别保留,编译时 就会被忽略,在class字节码文件中不包含。
RetentionPolicy.CLASS:这种类型的Annotations编译时被保留,默认的保留策略,在class文件中存在,但JVM将会忽略,运行时无法获得。
RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。

@Document:说明该注解将被包含在javadoc中

@Inherited:说明子类可以继承父类中的该注解

总结:

三个值中SOURCE < CLASS < RUNTIME,即CLASS包含了SOURCE,RUNTIME包含SOURCE、CLASS

反射

下面先看代码

 public static void injectView(Activity activity) {
        //获取class
        Class cla = activity.getClass();
        //获取对应class下所有属性
        Field[] fields = cla.getDeclaredFields();
        for (Field field : fields) {
            //判断是否有我们注解
            boolean isEsite = field.isAnnotationPresent(AnnotateFindView.class);
            if (isEsite) {
                AnnotateFindView annotation = field.getAnnotation(AnnotateFindView.class);
                int idResource = annotation.value();
                View view = activity.findViewById(idResource);
                field.setAccessible(true);
                try {
                    field.set(activity, view);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

    }

结合注解就可以省略getIntent

//创建注解
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityValue {
    String value() default "";
}
//反射赋值
public static void injntActivity(Activity activity) {
        Class cla = activity.getClass();

        Intent intent = activity.getIntent();
        Bundle extras = intent.getExtras();

        if (extras == null) {
            return;
        }
        Field[] fields = cla.getDeclaredFields();

        for (Field field : fields) {
            boolean isExsit = field.isAnnotationPresent(ActivityValue.class);
            if (isExsit) {
                ActivityValue annotation = field.getAnnotation(ActivityValue.class);
                String key = TextUtils.isEmpty(annotation.value()) ? field.getName() : annotation.value();
                Object obj = extras.get(key);
                Class type = field.getType().getComponentType();
                if (field.getType().isArray() &&null!=type&& Parcelable.class.isAssignableFrom(type)) {
                    Object[] objs = (Object[]) obj;
                    Class clas = (Class) field.getType();
                    obj = Arrays.copyOf(objs, objs.length, clas);
                }

                field.setAccessible(true);
                try {
                    field.set(activity, obj);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }

            }
        }

    }
//跳转
    mainActivity.btnStartIntent.setOnClickListener {
            val vo = UserData().apply {
                age = 2
                name = "小马哥"
                cla = "一年级二班"
            }
            val intent = Intent(this, ContentActivity::class.java).apply {
                putExtra("name", "小明")
                putExtra("age", 1)
                putExtra("vo", vo)
            }
            startActivity(intent)
        }

   

在跳转的ContentActivity 注解以下就可以了

 @ActivityValue
    var name: String? = null;

    @ActivityValue
    var age: Int? = null;

    @ActivityValue(value = "vo")
    var dataVo: UserData? = null;

结合上面就可以扩展个别控件设置背景

你可能感兴趣的:(注解和反射)