注解框架的原理理解
来源:互联网 发布:linux开机启动流程 编辑:程序博客网 时间:2024/06/06 04:01
关注注解 我想都不陌生了,Android上采用注解来快速开发 我在实际工作中还没试过,这里简介记录一下我对Android注解框架的理解。
注解在Android开发中大致可以分为用在 方法 、成员、和 事件上,其他暂时不考虑。
本文参考知名博主张鸿洋的 关于IOC的描述 地址:
http://blog.csdn.net/lmj623565791/article/details/39269193
一、注解反射成员变量和 方法。编写反射@interface xxx
引用注解,反射得到注解的值,传递进入当前Context反射得到Method。Field 等,然后执行invoke 方法即可
这样可以通过注解反射成员变量(可以初始化控件),成员方法(加载布局文件)等。比较简单。
btn = findViewById:可能需要多个btn,因此写注解是多个的。@inject(value=id)Class<? extends Activity> clazz = activity.getClass(); Field[] fields = clazz.getDeclaredFields(); // 遍历所有成员变量 for (Field field : fields) { ViewInject viewInjectAnnotation = field.getAnnotation(ViewInject.class); }setOnContentView(id) :由于一个类只有个layout布局设置,所以只需要一个annotation就行了.(@contentview(value=id)) Class<? extends Activity> clazz = activity.getClass(); ContentView contentView = clazz.getAnnotation(ContentView.class);
以上是注解反射字段和 反射方法。
二、通过注解注入事件。
下面这样的代码btn.setOnclickListener(new View.OnclickListener(){onclick })将改为:@Onclick(value=R.id.btn1,value=R.id.btn2...)public void myClick(View v){}
1、反射得到btn
利用注解拿到id后 findviewById(id),得到Button
2、利用Proxy InvocationHandler 创建接口(View.OnclickListener)的对象,可以自定义一个类实现InvocationHandler 。
例如下面代码:
main:test:InvocationHandler i = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.out.println("方法名:"+method.getName());System.out.println((args==null)?"没有参数":"参数:"+args[0]);System.out.println(method.getReturnType().getName());System.out.println();return "test result";}};//利用Proxy创建出接口InterfaceTest的对象,Object o = Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{InterfaceTest.class}, i);//转化为InterfaceTest对象InterfaceTest interfaceTest = (InterfaceTest) o;//当调用对象的方法时,也就是接口中的方法时就会调用InvocationHandler的invoke方法。上面的i就是代理对象。String result1 = interfaceTest.printInfo1();interfaceTest.printInfo2();String result = interfaceTest.printInfo3("1");System.out.println(result);publicinterface InterfaceTest{public String printInfo1();public void printInfo2();public String printInfo3(String p);}
3、反射执行setOnclickListener
总体思想是把下面这句代码,封装起来,只把控件id和自己定义的事件处理方法 提供给程序员来写。
btn.setOnclickListener(new View.OnclickListener(){onclick })@Onclick(value=R.id.btn1,value=R.id.btn2...)public void myClick(View v){}
那么可以推测到有个注解 @interface Onclick。这个@interface Onclick注解里面得完成btn.setOnclickListener(new View.OnclickListener(){onclick }) 操作。而@interface Onclick是个注解。
所以只有在这个注解上再次使用一个注解。于是乎有:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @EventBase(listenerType = View.OnClickListener.class, listenerSetter = "setOnClickListener", methodName = "onClick") public @interface Onclick{//放置控件的idint[] value;}
那么在 @interface EventBase中来提供 设置listener的元素:监听类的类型(OnclickListener.class),类型名称(setOnclickListener),监听类的方法也就是事件的处理方法
(onClick),有了这三个元素就可以 在验证@interface EventBase注解时 完成btn.setOnClickListener(obj)操作.
下面是实现的代码:
/** * 注入所有的onclick事件 * * @param activity */private static void injectEvents(Activity activity){Class<? extends Activity> clazz = activity.getClass();Method[] methods = clazz.getMethods();//遍历当前activity中的所有方法for (Method method : methods){Annotation[] annotations = method.getAnnotations();//拿到方法上的所有的注解,这里可以拿到 @interface Onclick注解for (Annotation annotation : annotations){ Class<? extends Annotation> annotationType = annotation.annotationType();//拿到@interface EventBase注解,因为这个注解上提供了反射执行btn.setOnclickListener(obj)的元素。//这个注解是@interface Onclick注解上的注解。EventBase eventBaseAnnotation = annotationType.getAnnotation(EventBase.class);//如果设置的为EventBase注解if (eventBaseAnnotation != null){//取出设置监听器的类型,监听器的名称,监听器的方法(事件回调执行方法onClick)String listenerSetter = eventBaseAnnotation.listenerSetter(); //setOnclickListenerClass<?> listenerType = eventBaseAnnotation.listenerType();//OnclickListener.classString methodName = eventBaseAnnotation.methodName();//onClicktry{//拿到Onclick注解中的value方法:拿到控件的id,以此可以得到btn控件实例Method aMethod = annotationType.getDeclaredMethod("value");//取出所有的viewId,value()方法不需要参数,所以是nullint[] viewIds = (int[]) aMethod.invoke(annotation, null);//通过Proxy InvocationHandler创建代理对象。即OnclickListener接口的对象。DynamicHandler handler = new DynamicHandler(activity);handler.addMethod(methodName, method);// 这句可以不要Object listener = Proxy.newProxyInstance(listenerType.getClassLoader(),new Class<?>[] { listenerType }, handler);//到此即可设置事件了:for (int viewId : viewIds){//遍历所有的View,创建出view ,View view = activity.findViewById(viewId);//再利用view反射出事件方法名并得到此方法的Method对象,Method setEventListenerMethod = view.getClass().getMethod(listenerSetter, listenerType);//最后利用Method对象设置事件即可.btn.setOnclickListener(obj);//setOnclickListener方法对象反射执行,参数为所属对象和方法参数。setEventListenerMethod.invoke(view, listener);}} catch (Exception e){e.printStackTrace();}}}}}
方便快速开发的 注解框架基本原理 我理解就是这个了,下面是如何使用的问题,比较简单。
@ContentView(value = R.layout.activity_main) //在类上加上注解 ,用来设置布局文件public class MainActivity extends Activity implements OnClickListener { @ViewInject(R.id.id_btn) private Button mBtn1; //在定义控件的字段成员上加上注解,用来初始化控件。 @ViewInject(R.id.id_btn02) private Button mBtn2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ViewInjectUtils.inject(this); //验证自定义的注解,也就是一些初始化工作等。 } }public static void inject(Activity activity) { injectContentView(activity); injectViews(activity); injectEvents(activity); }
0 0
- 注解框架的原理理解
- KJFrameForAndroid框架学习----深入理解注解原理
- KJFrameForAndroid框架学习----深入理解注解原理
- springmvc框架原理的一些理解
- 深入理解Java 注解原理
- Android注解原理与常用注解框架
- 深入理解编译注解(六)Butterknife的实现原理
- Java框架原理之注解
- java注解的理解和框架中的利用
- Android ButterKnife 注解框架的使用详解和原理分析
- 注解的理解、自定义注解
- 有待理解的 CI框架缓存的实现原理
- Java注解的理解
- java注解的理解
- 注解的理解
- spring注解的理解
- 注解的一些理解
- 注解的原理
- 关于深入剖析Linux动态库链接过程的文章与资源
- 使用 GROUP BY WITH ROLLUP 改善统计性能 .
- SSRS 的dataset
- 多线程之-NSOperation
- Windchill开发资料下载网址
- 注解框架的原理理解
- apache tools压缩成zip格式的文件
- 在Java中使用脚本语言 javax.script探秘
- Animation and Graphics Overview
- hznu 1441 Greatest Number(选出4个数,使值最接近m)
- openfire启动问题
- android(6) 扇形菜单实现
- awk命令详解
- 第六届ACM省赛总结--乔璐