注解也算是常用的,但大多都是用用,并不能明白很多细节及原理;
我通过注解和反射来模拟一个ButterKinfe场景
先说说注解
通过@interface ,@Target(),@Retention,要描述
如:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView {
@IdRes int value();
}
@Target() @Retention() 表示注解上的注解,简单来说他们也是注解,对下面刚创建的这个注解进行声明
@Target() 表示声明这个注解在那些节点上使用;它有三个值
RetentionPolicy.SOURCE
标记的注解仅保留在源级别中,并被编译器忽略。
RetentionPolicy.CLASS
标记的注解在编译时由编译器保留,但 Java 虚拟机(JVM)会忽略。意思是在编译成javac时就会使用它,把它代码注入到字节中;
RetentionPolicy.RUNTIME
标记的注解由 JVM 保留,因此运行时环境可以使用它
SOURCE < CLASS < RUNTIME,即CLASS包含了SOURCE,RUNTIME包含SOURCE、CLASS。
它们运用场景:
SOURCE:源码,场景 APT,在编译时获取到注解及注解的声明的类,及所有成员信息,类似于编译器场景;
CLASS:字节码,场景 字节码增强,在编译出Class后,通过修改Class数据以实现修改代码逻辑目的。对于是否需要修改的区分或者修改为不同逻辑的判断可以使用注解。
RUNTIME:运行时,场景 反射;在程序运行期间,通过反射技术动态获取注解与其元素,从而完成不同的逻辑判定。
反射:
正常情况下我们是new 对象实例,进行使用它的方法属性;但不知道这个对象是什么,就可以用反射;
反射就是在运行状态中,通过任意一个类,通过反射知道这个类及属性和方法;
getFied()和getDeclareField()的区别,前者是获取到的是当类及父类的属性;getDeclaredFiled()获取到是当前属性,获取不到父类的属性;
这两个实例代码:
创建一个InjectUtils.class
public class InjectUtils {
public static void injectView(Activity activity){
Class<? extends Activity> className = activity.getClass();
Field[] fields = className.getDeclaredFields();
for(Field f : fields){
//判断属性上有InjectView 的注解
if (f.isAnnotationPresent(InjectView.class)){
//获取注解器
InjectView injectView = f.getDeclaredAnnotation(InjectView.class);
//通过注解获取当前属性中设置的值
int id = injectView.value();
//通过在activity 中设置的id,查找View
View view = activity.findViewById(id);
//反射设置,属性值;设置访问权限,允许操作private的属性
f.setAccessible(true);
try {
//反射赋值,把获取到的view,赋值到activity 中属性中
f.set(activity,view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
创建一个注解:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView {
@IdRes int value();
}
MainActivity中使用:
@InjectView(R.id.tv_name)
private TextView tvName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InjectUtils.injectView(this);
tvName.setText("Inject Success!");
}
java注解(annotation)有称为java标注,是JDK1.5引入的一种注释机制。提供有关于程序但不属于程序本身的数据。注解对它们注解的代码操作并没有直接的影响;
注解单独用没有多大的意义; |