Android注解(annotation)实现绑定事件的原理
Posted tangjiean
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android注解(annotation)实现绑定事件的原理相关的知识,希望对你有一定的参考价值。
注解是一种很优雅的书写方式,也是我们的代码变的简洁,更加快捷方便编写代码。下面以绑定onclick实践为例阐述注解的原理。
1、定义Onclick注解类
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@BaseEvent(listenerSetter = "setOnclickListener",
listenerType = View.OnClickListener.class,
methodName = "onclick")
public @interface OnClick
int[] values();
BaseEvent用来制定需要绑定的方法名,事件的Listener,和绑定执行的方法名,BaseEvent的代码如下
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface BaseEvent
Class<?> listenerType();
String listenerSetter();
String methodName();
2、自定义的注解使用方式
@OnClick(R.id.download_btn)
public void testUpload(View view)
3、注解的解析(重点):
思路:可以通过我们的注解对象中取得添加onclick注解的方法(testUpload)反射方法对象,对这个对象进行事件的绑定。动态代理View事件中的OnclickLister,向代理对象中添加方法对象(testUpload)。方法的添加在EventListenerManager管理类中完成。
EventLisernerManager中定义动态代理类:
public static void addEventMethod(Method method,
Annotation annotation,
Object value,
Object handler,
ViewFinder finder)
try
View view = finder.findViewByInfo(value);
if(view!=null)
BaseEvent baseEvent = annotation.annotationType().getAnnotation(BaseEvent.class);
Class<?> listenerType = baseEvent.listenerType();
String listenerSetter = baseEvent.listenerSetter();
String methodName = baseEvent.methodName();
Object listener = listenerCache.get(value, listenerType);
boolean addMethod = false;
DynamicHandler dymicHandler = null;
if(listener!=null)
dymicHandler = (DynamicHandler) Proxy.getInvocationHandler(listener);
addMethod = (handler.equals(dymicHandler.getHandler()));
if(addMethod)
dymicHandler.addMethod(methodName, method);
if(!addMethod)
dymicHandler = new DynamicHandler(handler);
dymicHandler.addMethod(methodName, method);
listener = Proxy.newProxyInstance(listenerType.getClassLoader(),
new Class<?>[]listenerType,dymicHandler);
listenerCache.put(value, listenerType, listener);
//setListener
Method setterMethod = view.getClass().getMethod(listenerSetter, listenerType);
setterMethod.invoke(view, listener);
catch(Exception e)
LogUtils.e(e.getMessage(),e);
listener = Proxy.newProxyInstance(listenerType.getClassLoader(),new Class<?>[]listenerType,dymicHandler);动态的代理了onClickListener。类中对代理对象进行的缓存:
//缓存代理对象
public final static DoubleKeyValueMap<Object,Class<?>, Object> listenerCache = null;
解析注解添加方法:
Method[] methods = handlerType.getDeclaredMethods();
if(methods.length>0)
for(Method method:methods)
Annotation[] annotations = method.getDeclaredAnnotations();
for(Annotation annotation : annotations)
Class<?> anType = annotation.annotationType();//拿到Annotation的Class
if(anType.getAnnotation(BaseEvent.class)!=null)
method.setAccessible(true);
try
Method valueMethod = anType.getDeclaredMethod("values");
Object values = valueMethod.invoke(annotation);
int len = Array.getLength(values);
if(len>0)
for(int i=0;i<len;i++)
Object value = Array.get(values, i);
EventListenerManager.addEventMethod(method, annotation, value, handlerType, finder);
catch(Exception e)
e.printStackTrace();
这里可以拿到自定义method和注解本身。不太了解的可以研究下java的annotation的用法。
由以上的方法的可以实现注解事件的绑定,可以自己定义事件的注解,优雅的开始你的代码吧!
以上是关于Android注解(annotation)实现绑定事件的原理的主要内容,如果未能解决你的问题,请参考以下文章
Android开发学习之路--Annotation注解简化view控件之初体验
一小时搞明白注解处理器(Annotation Processor Tool)
一小时搞明白注解处理器(Annotation Processor Tool)