目的
使用注解代替setContentView(),findViewById(),onClick()和onLongClick()的点击事件
如图一、实现setContentView()
1、先写个注解InjectLayout(1)@interface:注解的写法(声明)
(2)@Target:目标(此注解作用在什么地方)一下是常用的几个
ElementType.TYPE:类名之上
ElementType.FIELD:属性字段之上(成员变量)
ElementType.METHOD:方法之上
ElementType.CONSTRUCTOR:构造函数
ElementType.LOCAL_VARIABLE:局部变量
ElementType.ANNOTATION_TYPE:注解之上(注解的注解 称为原注解(3)@Retention 注解在哪个阶段保留也就是可见
RetentionPolicy.SOURCE:源码阶段
RetentionPolicy.CLASS:在类文件时
RetentionPolicy.RUNTIME:运行时
(4)int value():int类型参数
以上先简单的介绍下注解的含义 下面开始撸码
首先创建个InjectManage注入管理类一个inject方法 外部调用此方法注入思路
1)通过obj获取到Class对象
Class<?> clazz = obj.getClass();
2)通过Class对象获取到类注解
InjectLayout injectLayout = clazz.getAnnotation(InjectLayout.class);
3)判断当前类是否有注解(也就是区分Activity类和普通的Test类)
3.1:如果injectLayout不为空就是有注解
4)如果有注解通过Class对象,反射获取到setContentView方法
Method setContentView = clazz.getMethod("setContentView", int.class);
getMethod()获取公共方法
getDeclaredMethod() 获取所有的包括公共 私有…方法
param1:方法名
param2:方法的参数类型
5)获取到注解参数
int value = injectLayout.value();
value相当于R.layout.activity_main
6)执行获取到的setContentView方法
setContentView.invoke(obj, value);
- 整体代码
二、实现findViewById()
1、写个注入控件View的注解InjectView
这里Target要改成FIELD,因为这是作用在属性之上的
我们在injectLayout方法下增加injectView方法
2、获取Class对象
Class<?> clazz = obj.getClass();
3、获取所有属性
Field[] fields = clazz.getDeclaredFields();
4、遍历属性,判断是否有InjectView注解
InjectView injectView = field.getAnnotation(InjectView.class);
5、通过反射获取到findViewById方法
Method findViewById = clazz.getMethod("findViewById", int.class);
6、获取参数 执行findViewById方法
int value = injectView.value();
View view = (View) findViewById.invoke(obj, value);
注意;到这里只是执行了findViewById方法 并没有给控件赋值
7、给空间赋值
//因属性有私有的 这里设置为可访问课操作
field.setAccessible(true);
//给控件赋值
field.set(obj, view);
8、完整方法代码
三、onClick和onLongClick
直接上代码也就是以上两个的扩容
1、onClick注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
//这个注解为原注解 是作用在注解之上的 用来用来区分方法的注解
@InjectEvent(listenerSetting = "setOnClickListener", listenerType = View.OnClickListener.class,
callBackMethod = "onClick")
public @interface OnClick {
//点击事件 有可能有多个
int[] value();
}
onLongClick注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@InjectEvent(listenerSetting = "setOnLongClickListener", listenerType = View.OnLongClickListener.class,
callBackMethod = "onLongClick")
public @interface OnLongClick {
int[] value();
}
InjectEvent原注解
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectEvent {
//事件三要素
//方法名
String listenerSetting();
//参数类型
Class listenerType();
//回调方法
String callBackMethod();
}
整体方法
private static void injectEvent(Object obj) {
Class<?> clazz = obj.getClass();
//获取所有方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
//获取所有注解
Annotation[] annotations = method.getAnnotations();
for (Annotation annotation : annotations) {
//获取注解对象的class
Class<? extends Annotation> annotationType = annotation.annotationType();
//获取InjectEvent注解对象
InjectEvent injectEvent = annotationType.getAnnotation(InjectEvent.class);
if (injectEvent != null) {
//获取参数
String listenerSetting = injectEvent.listenerSetting();
Class listenerType = injectEvent.listenerType();
String callBackMethod = injectEvent.callBackMethod();
ListenerHandler listenerHandler = new ListenerHandler(obj, method);
//动态代理
Object listener = Proxy.newProxyInstance(listenerType.getClassLoader(),
new Class[]{listenerType}, listenerHandler);
try {
//获取注解里value 相当于注解之上的所有Id
Method valueMethod = annotationType.getDeclaredMethod("value");
int[] ids = (int[]) valueMethod.invoke(annotation);
for (int id : ids) {
Method findViewById = clazz.getMethod("findViewById",int.class);
View btn = (View) findViewById.invoke(obj, id);
//setOnClickListener的method对象
Method setterMethod = btn.getClass().getMethod(listenerSetting, listenerType);
//btn.setOnClickListener
//第二个参数 new View.OnClickListener
setterMethod.invoke(btn, listener);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
动态代理
public class ListenerHandler implements InvocationHandler {
private Object object;
private Method mMethod;
public ListenerHandler(Object object, Method method) {
this.object = object;
this.mMethod = method;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return mMethod.invoke(object, args);
}
}
第一次写文章记录,写的不好还忘海涵~~~以后多多努力~~~