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)

一小时搞明白注解处理器(Annotation Processor Tool)

Android Afinal框架

手写ButterKnife