ButterKinfe原理,并简单仿照ButterKinfe定义自己的ButterKnife
2016-04-14 10:33
302 查看
以7.0.0版本进行分析,其本质就是注解加反射
在使用butterKinfe的时候先绑定,其实就是获得注解的对象,之后扫描这个对象的字节码的所有的filed和method,符合我们注解的就保存下来
当符合filed的时候,就给filed通过反射赋值
当符合method的时候,就给method对应的id的view设置监听,之后回调method方法
接下来我们手把手定义自己的ButterKinfe
先定义注解bind,用来减少findviewbyid的
`package com.example.admin.butterkinfe.butterkinfe;
`
* 之后定义我们的OnClick注解
`
* 接下来也就是我们的butterKinfe主类,在使用butterKinfe的时候,需要先bind
`
* 方法其实很简单,就是扫描bind对象的所有的注解,之后反射赋值或者反射调用
在使用butterKinfe的时候先绑定,其实就是获得注解的对象,之后扫描这个对象的字节码的所有的filed和method,符合我们注解的就保存下来
当符合filed的时候,就给filed通过反射赋值
当符合method的时候,就给method对应的id的view设置监听,之后回调method方法
接下来我们手把手定义自己的ButterKinfe
先定义注解bind,用来减少findviewbyid的
`package com.example.admin.butterkinfe.butterkinfe;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by admin on 2016/4/14. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Bind { int value(); }
`
* 之后定义我们的OnClick注解
`package com.example.admin.butterkinfe.butterkinfe; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by admin on 2016/4/14. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface OnClick { int[] value(); }
`
* 接下来也就是我们的butterKinfe主类,在使用butterKinfe的时候,需要先bind
`package com.example.admin.butterkinfe.butterkinfe; import android.app.Activity; import android.view.View; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * Created by admin on 2016/4/14. */ public class ButterKinfe { private static Map<Integer,View> hashMap=new HashMap<>(); public static void bind(Object object) { //类,扫描属性和方法,之后给这个方法复制 scannner(object); } private static void scannner(Object object) { scannerFiled(object);//扫描所有的field,找到符合条件的赋值 scannerMethod(object);//扫描所有的method,找的符合条件的进行回调 } private static void scannerMethod(final Object object) { Method[] methods = object.getClass().getDeclaredMethods(); for(final Method m:methods){ if(m.isAnnotationPresent(OnClick.class)){ m.setAccessible(true); OnClick annotation = m.getAnnotation(OnClick.class); int[] id= annotation.value(); for(int i=0;i<id.length;i++){ final View view= hashMap.get(i); if(view!=null){ view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { m.invoke(object,v); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }); }else{ Activity a= (Activity) object; final View temp=a.findViewById(id[i]); temp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { m.invoke(object,v); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }); } } } } } private static void scannerFiled(Object object) { Field[] fields = object.getClass().getDeclaredFields(); for (Field f : fields) { boolean annotationPresent = f.isAnnotationPresent(Bind.class); if (annotationPresent) { f.setAccessible(true); Bind bind = f.getAnnotation(Bind.class); int id = bind.value(); Activity a = (Activity) object; try { View view= a.findViewById(id); hashMap.put(id,view); f.set(object,view); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } }
`
* 方法其实很简单,就是扫描bind对象的所有的注解,之后反射赋值或者反射调用
相关文章推荐
- jsp中超链接路径的写法
- 剑指offer 旋转数组的最小数字
- javascript 高级程序设计 十一
- css javascript嵌入html5文件
- 前端通信进阶
- Js闭包常见三种用法
- CSS中关于多个class样式设置的不同写法
- Kindeditor在线文本编辑器如何过滤HTML
- ES6简明教程: 概述与比较
- 关于jquery获取元素高度、height、scrollTop等问题,更新。。。
- 用JS或者jQuery监听 浏览器窗口大小的变化事件
- html加强
- MANIFEST.MF的用途(转载)
- 假分页 js分页 查询出所有数据再分页
- 基于RequireJS和JQuery的模块化编程日常问题解析
- HTML一些小技巧
- 【转】AngularJS 最常用的八种功能
- algrothm_different【Integer+int】
- [caffe]将自己的图片数据转换db格式
- Toolbar上overflow的样式自定义详解