Xutils3如何导入到项目这里就不做介绍了,网上很多教程,我们这里只是阅读源码了。
首先来看下基本的使用方法吧,根据github上面的我们都是这样进行Xutils的初始化了
x.view().inject(this);
在使用Xutils对View进行注入的时候,其实是通过反射拿到传入的this(当前Activiy),再通过反射拿到我们平时所使用的setContextView()方法,拿到对应的函数之后调用invoke(),去执行当前方法,绕了一圈其实最后调用的还是setContentView();
public void inject(Activity activity) { //获取Activity的ContentView的注解 Class<?> handlerType = activity.getClass(); try { ContentView contentView = findContentView(handlerType); if (contentView != null) { int viewId = contentView.value(); if (viewId > 0) { Method setContentViewMethod = handlerType.getMethod("setContentView", int.class); setContentViewMethod.invoke(activity, viewId); } } } catch (Throwable ex) { LogUtil.e(ex.getMessage(), ex); } injectObject(activity, handlerType, new ViewFinder(activity)); }
这一段代码主要是通过反射去获得所有的属性
ViewInject viewInject = field.getAnnotation(ViewInject.class); if (viewInject != null) { try { View view = finder.findViewById(viewInject.value(), viewInject.parentId()); if (view != null) { field.setAccessible(true); field.set(handler, view); } else { throw new RuntimeException("Invalid @ViewInject for " + handlerType.getSimpleName() + "." + field.getName()); } } catch (Throwable ex) { LogUtil.e(ex.getMessage(), ex); } }
这才是上面的注释所标明的地方啊,ViewInject,通过拿到ViewInject这个注解,再通过viewInject.value()去拿到对应的资源文件的int值,再通过findViewById去查找View,到这里我们平时所使用的多么高大上的框架,最终也是调用了我们平时所写的那么几个简单的代码。
属性注入:利用反射去获取Annotation,然后获得对应的value(资源文件int值),调用findViewById(),再通过反射去注入属性
事件注入:利用反射去获取Annotation,然后获得对应的value(资源文件int值),调用findViewById(),再通过反射拿到View.OnClickListener,拼接一个set,反射去调用SetOnClickListener(),再通过动态代理反射执行方法。
// inject event Method[] methods = handlerType.getDeclaredMethods(); if (methods != null && methods.length > 0) { for (Method method : methods) { if (Modifier.isStatic(method.getModifiers()) || !Modifier.isPrivate(method.getModifiers())) { continue; } //检查当前方法是否是event注解的方法 Event event = method.getAnnotation(Event.class); if (event != null) { try { // id参数 int[] values = event.value(); int[] parentIds = event.parentId(); int parentIdsLen = parentIds == null ? 0 : parentIds.length; //循环所有id,生成ViewInfo并添加代理反射 for (int i = 0; i < values.length; i++) { int value = values[i]; if (value > 0) { ViewInfo info = new ViewInfo(); info.value = value; info.parentId = parentIdsLen > i ? parentIds[i] : 0; method.setAccessible(true); EventListenerManager.addEventMethod(finder, info, event, handler, method); } } } catch (Throwable ex) { LogUtil.e(ex.getMessage(), ex); } } } } // end inject event