参考:https://www.jianshu.com/p/20da6d6389e1
ViewInject.java
/**
* @Retention 用于声明该注解生效的生命周期,有三个枚举值可以选择<br>
* 1. RetentionPolicy.SOURCE 注释只保留在源码上面,编译成class的时候自动被编译器抹除
* 2. RetentionPolicy.CLASS 注释只保留到字节码上面,VM加载字节码时自动抹除
* 3. RetentionPolicy.RUNTIME 注释永久保留,可以被VM加载时加载到内存中
* 注意:由于我们的目的是想在VM运行时对Filed上的该注解进行反射操作,因此Retention值必须设置为RUNTIME
*
* @Target 用于指定该注解可以声明在哪些成员上面,常见的值有FIELD和Method,
由于我们的当前注解类是想声明在Filed上面
* 因此这里设置为ElementType.FIELD。
* 注意:如果@Target值不设置,则默认可以添加到任何元素上,不推荐这么写。
*
* @interface 是声明注解类的组合关键字。
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewInject {
public abstract int value();
}
Onclick.java
@Target({java.lang.annotation.ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Onclick {
public abstract int[] value();
}
ViewUtils.java
public class ViewUtils {
public static void inject(final Activity activity) {
Class clazz = activity.getClass();
Field[] declaredFields = clazz.getDeclaredFields();
for (int i = 0; i < declaredFields.length; i++) {
Field field = declaredFields[i];
field.setAccessible(true); //暴力访问
ViewInject annotation = field.getAnnotation(ViewInject.class);
if (annotation == null) {
continue;
}
int id = annotation.value();
View view = activity.findViewById(id);
try {
field.set(activity, view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
Method[] declaredMethods = clazz.getDeclaredMethods();
for (int i = 0; i < declaredMethods.length; i++) {
final Method method = declaredMethods[i];
Onclick annotation = method.getAnnotation(Onclick.class);
if (annotation == null) {
continue;
}
int[] value = annotation.value();
for (int j = 0; j < value.length; j++) {
int id = value[j];
final View button = activity.findViewById(id);
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
try {
method.invoke(activity,button);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
}
}
}
}
Test类
public class Activity_InjectTest extends AppCompatActivity {
@ViewInject(R.id.btn_1)
Button btn_1;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_inject);
ViewUtils.inject(this);
}
@Onclick(R.id.btn_1)
public void onClick(View view){
switch (view.getId()){
case R.id.btn_1:
Log.e("dmj","btn_1");
break;
}
}
}