1.setContentView绑定
//注解
/**
* Created by dell on 2018/1/24.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Inherited
public @interface ContentView {
int value();
}
2.实现控件绑定
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
@Inherited
public @interface BindView {
int value();
}
3.实现控件的点击事件绑定
//注解的应用注释
public @interface EventControl {
/**
* 设置事件监听的方法
* @return
*/
String listenerMethod();
/**
* 设置事件回调的方法
* @return
*/
String callBack();
/**
* 获取监听类型
* @return
*/
Class<?> getClazzType();
}
//注解@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Inherited
@EventControl(
listenerMethod = "setOnClickListener",
callBack = "onClick",
getClazzType = View.OnClickListener.class)
public @interface OnClick {
int[] value();//对一组数据添加监听
}
//注解工具类public class InjectUtil {
/**
* 注入activity,作用是通过反射,运行相关逻辑
* @param activity
*/
public static void inject(Activity activity){
inJectContentView(activity);
inJectViews(activity);
inOnclick(activity);
}
private static void inOnclick(final Activity activity) {
Method[] methods = activity.getClass().getMethods();
for (Method method : methods) {
//1.获取方法上的所有注解
Annotation[] annotations = method.getAnnotations();
//2判断注解是否是我们需要的注解:也就是注解上是否包含event
for (Annotation annotation : annotations) {
Class<? extends Annotation> annotationType = annotation.annotationType();
//获取注解上是否有我们约定好的注解
EventControl eventControl = annotationType.getAnnotation(EventControl.class);
if (eventControl == null) {
//说明不是我们想要的注解,跳出此次循环
continue;
}
//获取注解上声明好的内容
String listener = eventControl.listenerMethod();
String callback = eventControl.callBack();//要拦截的方法
Class<?> listenerType = eventControl.getClazzType();
final Map<String, Method> methodMap = new HashMap<>();
methodMap.put(callback, method);
try {
Method valueMethod = annotationType.getDeclaredMethod("value");
//第一个参数是接受者,也就是这里的注解对象,也就是调用annotation的value方法,如果后面有参数
//则在后面声明不定参数
int[] viewIds = (int[]) valueMethod.invoke(annotation);
//遍历id找到view
for (int viewId : viewIds) {
final View view = activity.findViewById(viewId);
if (view != null) {
//给view添加监听
if (view == null) {
continue;
}
//获取设置监听的方法,但是不知道对什么设置监听:onClick,onItemClick...
Method setListenerMethod = view.getClass().getMethod(listener, listenerType);
//这里只有listener的类型
//根据对应类型生成对应的代理类对象
Object proxyInstance = Proxy.newProxyInstance(listenerType.getClassLoader(), new Class[]{listenerType}, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (methodMap != null) {
//获取对应方法在map中是否存在,这里的是我们的handle方法
Method m = methodMap.get(method.getName());
if (m != null) {
//调用存入map中的方法,也就是我们在activity中声明监听注解的方法
return m.invoke(activity, args);
}
}
return method.invoke(proxy, args);
}
});
//给view设置监听
setListenerMethod.invoke(view, proxyInstance);
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
private static void inJectViews(Activity activity) {
//得到Activity字节码
Class clazz= activity.getClass();
//得到activity的所以成员变量
Field[] fields = clazz.getDeclaredFields();
if(fields!=null&&fields.length>0){
for (Field field:fields) {
//设置权限
field.setAccessible(true);
//得到成员变量上面的注解
BindView bindView = field.getAnnotation(BindView.class);
if(bindView!=null){
//得到成员变量的值
int id = bindView.value();
Log.e("BindVIEW",id+"ASDASD");
//得到每个id的view
View view = activity.findViewById(id);
try {
//通过反射的方法初始化成员变量
field.set(activity,view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
private static void inJectContentView(Activity activity) {
//得到Activity字节码
Class clazz = activity.getClass();
//得到类上面的注解
ContentView contentView = (ContentView) clazz.getAnnotation(ContentView.class);
if(contentView!=null){
int layoutID = contentView.value();
try {
//获取方法
Method method = clazz.getMethod("setContentView",int.class);
//给方法赋值
method.invoke(activity,layoutID);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//mainActivity
@ContentView(R.layout.activity_main)
public class MainActivity extends AppCompatActivity{
@BindView(R.id.name_tv)
Button tv;
@BindView(R.id.btn)
Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
InjectUtil.inject(this);
tv.setText("男 难 南 楠 囡");
}
@OnClick(R.id.name_tv)
public void b1(View v){
Toast.makeText(this,"成功1",Toast.LENGTH_SHORT).show();
}
@OnClick(R.id.btn)
public void b2(View v){
Toast.makeText(this,"男 难 南 楠 囡",Toast.LENGTH_SHORT).show();
}
}