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的用法。

由以上的方法的可以实现注解事件的绑定,可以自己定义事件的注解,优雅的开始你的代码吧!

时间: 2024-08-23 23:13:55

Android注解(annotation)实现绑定事件的原理的相关文章

Java Android 注解(Annotation) 及几个常用开源项目注解原理简析

不少开源库(ButterKnife.Retrofit.ActiveAndroid等等)都用到了注解的方式来简化代码提高开发效率. 本文简单介绍下 Annotation 示例.概念及作用.分类.自定义.解析,并对几个 Android 开源库 Annotation 原理进行简析.PDF 版: Java Annotation.pdf, PPT 版:Java Annotation.pptx, Keynote 版:Java Annotation.key 完整版原文见:Java Android 注解(Ann

Android自定义工具类获取按钮并绑定事件(利用暴力反射和注解)

Android中为按钮绑定事件的有几种常见方式,你可以在布局文件中为按钮设置id,然后在MainActivity中通过findViewById方法获取按钮对象实例,再通过setOnClickListener为按钮绑定事件,如下所示: //1.获取控件 btn = (Button)findViewById(R.id.button1); //2.绑定事件 btn.setOnClickListener(new OnClickListener() { @Override public void onCl

Android 注解的一些应用以及原理

在这边文章之前你首先需要对java 的注解部分有一个基本的了解(不需要太过的深入). 简单来说,注解这个东西就是用于辅助我们开发java代码的,注解本身无法干扰java源代码的执行. 在android 里面 注解主要用来干这么几件事: 1.和编译器一起给你一些提示警告信息. 2.配合一些ide 可以更加方便快捷 安全有效的编写java代码.谷歌出的support-annotations这个库 就是主要干这个的. 3.和反射一起 提供一些类似于spring 可配置的功能,方便简洁(这部分有过j2e

基础知识:设置Android按钮与绑定事件

在前面 向应用添加一个新的Activity,我们使用了按钮,点击按钮进入一个新的 Activity.这里简单总结一下按钮在 Android 的使用. 设计一个按钮很简单,在 IDE 里一般都有图形界面,你也可以自己在 xml 里自己编写,比如:澳门赌场玩法 view source print? 1 <Button 2     android:id="@+id/nowamagicbtn" 3     android:layout_width="wrap_content&q

java基础-注解Annotation原理和用法

在很多java代码中都可以看到诸如@Override.@Deprecated.@SuppressWarnings这样的字符,这些就是注解Annotation.注解最早在jdk5中被引入,现在已经成为java平台很重要的一部分了,很多的框架程序中也喜欢使用注解,如Spring.Mybatis等. 那么,什么是注解呢?注解就是元数据,一种描述数据的数据,通俗一点就是为程序的元素(类.方法.成员变量)加上更直观的说明,这些说明信息是与程序的业务逻辑无关的.但是,我们可以通过java的反射机制来获取An

Android 注解框架对比

Java的注解(Annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记,标记可以加在包,类,属性,方法,本地变量上.然后你可以写一个注解处理器去解析处理这些注解(人称编译时注解),也可以在程序运行时利用反射得到注解做出相应的处理(人称运行时注解).       开发Android程序时,没完没了的findViewById, setOnClickListener等等方法,已经让大多数开发者头疼不已.好在市面上有所谓的注解框架可以帮助开发者简化一些过程.比较流行的有butte

Android-ButterKnife不能注解RatingBar(含ButterKnife部分原理以及View传递机制)

继续把之前的安卓外包的一些东西写出来. 文章结构:(1)RatingBar基本使用(自定义样式):(2)ButterKnife不能注解RatingBar以及在项目解决的方式:(3)ButterKnife原理以及View机制原理 一.RatingBar基本使用(自定义样式): (1)一个style样式: <style name="roomRatingBar" parent="@android:style/Widget.RatingBar"> <ite

Android注解使用之通过annotationProcessor注解生成代码实现自己的ButterKnife框架

前言: Annotation注解在Android的开发中的使用越来越普遍,例如EventBus.ButterKnife.Dagger2等,之前使用注解的时候需要利用反射机制势必影响到运行效率及性能,直到后来android-apt的出现通过注解根据反射机制动态编译生成代码的方式来解决在运行时不再使用发射机制,不过随着android-apt的退出不再维护,我们今天利用Android studio的官方插件annotationProcessor来实现一下自己的ButterKnife UI注解框架. 需

android注解使用详解(图文)

在使用Java的SSH框架的时候,一直在感叹注解真是方便啊,关于注解的原理,大家可以参考我的另一片文章Java注解详解.最近有时间研究了android注解的使用,今天与大家分享一下. android中注解的使用用到了GitHub上的开源框架androidannotations,下载地址.这个开源框架应该是目前使用人数最多的android注解框架了,主要是由于它设计的注解标签非常多,能够满足我们日常开发中的大部分需求.androidannotations将许多可以抽取出来的方法都包装成了注解标签供