IoC,控制反转(Inversion of Control,英文缩写为IoC)
要完成IoC框架,首先你需要了解注解与发射
开始代码片段
Activity setContentView注解
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
int value();
}
字段注解
@Retention(RetentionPolicy.RUNTIME)
public @interface BindView {
int value();
}
事件三要素注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BaseEvent {
String setMethodName();
Class<?> interfaceClass();
String callMethodName();
}
OnClick注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@BaseEvent(setMethodName = "setOnClickListener", interfaceClass = View.OnClickListener.class, callMethodName = "onClick")
public @interface OnClick {
int[] value();
}
OnLongClick注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@BaseEvent(setMethodName = "setOnLongClickListener", interfaceClass = View.OnLongClickListener.class, callMethodName = "onLongClick")
public @interface OnLongClick {
int[] value();
}
OnItemClick注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@BaseEvent(setMethodName = "setOnItemClickListener", interfaceClass = AdapterView.OnItemClickListener.class, callMethodName = "onItemClick")
public @interface OnItemClick {
int[] value();
}
* 动态代理
*/
public class EventInvocationHandler implements InvocationHandler {
//代理的方法
private Map<String,Method>map;
//代理的真实对象
private Object target;
public EventInvocationHandler(Map<String, Method> map, Object target) {
this.map = map;
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName=method.getName();
if(map.get(methodName)!=null){
return map.get(methodName).invoke(target,args);
}
return proxy;
}
}
注解contentview实现
//获取当前的类
Class cls = context.getClass();
//获取类上面的ContentView注解
ContentView contentViewAnnotation = (ContentView) cls.getAnnotation(ContentView.class);
if (contentViewAnnotation != null) {
//获取注解上的值
int value = contentViewAnnotation.value();
try {
//在类里面查找setContentView方法
Method setContentViewMethod = cls.getMethod("setContentView", int.class);
//setContentView调用
setContentViewMethod.invoke(context, value);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
注解字段的实现
//获取当前的类
Class cls = context.getClass();
//查找对应的属性
Field[] fields = cls.getFields();
//遍历属性找到BindView注解
for (Field field : fields) {
BindView bindView = field.getAnnotation(BindView.class);
if (bindView != null) {
//获取注解的值
int value = bindView.value();
try {
//获取findVIewById方法
Method findViewByIdMethod = cls.getMethod("findViewById", int.class);
//调用findViewById方法拿到返回值
Object view = findViewByIdMethod.invoke(context, value);
field.setAccessible(true);
//设置属性值
field.set(context, view);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
注解事件的实现
//获取当前的类
Class cls = context.getClass();
//获取类中申明的可见方法
Method[] methods = cls.getMethods();
for (Method method : methods) {
//获取方法上的所有注解
Annotation[] annotations = method.getAnnotations();
for (Annotation annotation : annotations) {
//获取注解的类型 此处为OnClick OnLongClick
Class<?> annotationType = annotation.annotationType();
//获取事件注解
BaseEvent baseEvent = annotationType.getAnnotation(BaseEvent.class);
if (baseEvent != null) {
//获取事件注解三要素
String setMethodName = baseEvent.setMethodName();
Class<?> interfaceClass = baseEvent.interfaceClass();
String callMethodName = baseEvent.callMethodName();
//为动态代理做准备
Map<String, Method> map = new HashMap<>();
map.put(callMethodName, method);
try {
//获取注解的方法 值OnClick OnLongClick
Method valueMethod = annotationType.getDeclaredMethod("value");
int[] values = (int[]) valueMethod.invoke(annotation);
for (int value : values) {
//通过注解的值 找到对应的view
Method findViewById = cls.getMethod("findViewById", int.class);
Object view = findViewById.invoke(context, value);
//获取事件的方法
Method setEventMethod = view.getClass().getMethod(setMethodName, interfaceClass);
//动态代理 代理context里面的方法
EventInvocationHandler eventInvocationHandler = new EventInvocationHandler(map, context);
Object proxy = Proxy.newProxyInstance(view.getClass().getClassLoader(), new Class<?>[]{interfaceClass}, eventInvocationHandler);
//调用方法,通过动态代理最终执行context里面的方法
setEventMethod.invoke(view, proxy);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
上面只是简单的实现,可能的内存泄露,大家可以考虑使用引用相关的知识!