阅读过Xutils3和butterKnife的源码之后,稍微比对了一下,俩个都写的非常nb~~
Xutils3通过源码发现,主要是通过反射去 获得属性,函数进行注入。
而butterKnife通过将一系列的参数拼接起来重新生成一个.java文件打包到apk里面。
so,我们还是来通过反射的方式打造自己的IOC注解框架吧。
public static void inject(ViewFinder finder , Object object){ injectFiled(finder , object); //属性注入 injectEvent(finder , object); //函数注入 } private static void injectFiled(ViewFinder finder, Object object) { //1:获取类里面的所有属性 Class<?> clazz = object.getClass(); //获取类里面的所有属性集合 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields){ //拿到类里面的属性上面的Annotation ViewById viewById = field.getAnnotation(ViewById.class); //2:获取ViewById的里面的resId的值 if (viewById != null ){ //拿到Annotation里面的resId值 int viewId = viewById.value(); //3:findViewById找到里面的View View view = finder.findViewById(viewId); if (view != null) { //4:动态注入找到的View field.setAccessible(true); try { field.set(object, view); } catch (IllegalAccessException e) { Log.e("--->", "ViewUtils inject failure.."); e.printStackTrace(); } } } }跟Xutils3的做法类似,通过反射去拿到当前类,再获得所有属性,对所有属性进行遍历,判断是否带有Annotation,拿到带有Annotation的属性进行View的注入、到这里,我们就完成了属性的注入了,我们在使用的时候就只需要
@ViewById(R.id.id_text) private TextView tv;
这样就像Xutils一样完成了属性的注入了,使用的时候
tv.setText("嘿嘿");也不会出现空指针了~~~下面我们来看下点击函数的注入吧。
private static void injectEvent(ViewFinder finder, Object object) { Class<?> clazz = object.getClass(); Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { OnClick clickMethod = method.getAnnotation(OnClick.class); if (clickMethod != null){ int[] viewIds = clickMethod.value(); for (int viewId : viewIds) { View view = finder.findViewById(viewId); boolean isCheckNet = method.getAnnotation(CheckNet.class) != null; if (view != null) { view.setOnClickListener(new DeclaredOnClickListener(method, object, isCheckNet)); } } } } }这里的原理和属性注入也是一样的,拿到带有Annotation的View之后,通过view.setOnClickListener来设置点击事件,在点击事件里通过反射去执行我们平时的OnClickListener(),到这里有没有觉得我们所使用的注解框架就是这么简单呢。