注解
定义数据
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 extends Activity> 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 extends Activity> 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 extends Object[]> clas = (Class extends Object[]>) 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;
结合上面就可以扩展个别控件设置背景