前言:IOC注解,目前已经有非常许多类似的jar包可以用了,
比如XUtils以及Butterkniful等这些框架都可以用来进行相应的开发。然而,
写着篇博客的目的并非让你去打造一款超过上面的框架,只是想让你了解
一下他们实现的原理,以后可以基于这个的基础上,对其进行扩展比如
目前的两款没有网络检查这一功能,可以加上,因为我们多数地方会用到。
如果真的需要做一个类似于他们的插件工具的话,也并非不可以,不过这个
涉及到插件的制作,这个就相对麻烦了。不说那么多,我们具体来看看,
他们最为基本的findviewbyid是如何实现的。
思路:核心的思路就是getClass获取到那个类,
然后得到里面所有的属性,
再遍历里面所有的属性,
通过反射得到传过来的id的值,得到这个id的值后再通过
这个值去得到View,得到View之后再对其进行事件注册,
基本上思路就以上的思路了。
实现过程:
1.定义一个对外的反射接口:ViewById
/** * Created by 廖成康 on 2017/4/19. */ /** * 注解所在的位置 * */ @Target(ElementType.FIELD) /** * 注解什么时候使用 * */ @Retention(RetentionPolicy.CLASS) public @interface ViewById { /** * 注解所传的参数 * * @return */ int value(); }
通过这个接口来获取外面的值
2.定义一个工具类,里面进行上述思路的操作
package com.example.baselibrary; import android.app.Activity; import android.view.View; import java.io.File; import java.lang.reflect.Field; /** * Created by 廖成康 on 2017/4/19. */ public class ViewUtils { public static void inject(Activity activity) { inject(new ViewFinder(activity),activity); } public static void inject(View view) { inject(new ViewFinder(view),view); } public static void inject(View view,Object object) { inject(new ViewFinder(view),object); } /** * 对此进行分层,1.事件注解,2.属性注解 * * 并且对三个类进行兼容,反射需要执行的方法 * * @param finder * @param object */ public static void inject(ViewFinder finder,Object object) { injectEvents(finder,object); injectFild(finder,object); } //属性注解 private static void injectFild(ViewFinder finder, Object object) { /** * 获取到传入进来的类 * */ Class<?> clazz=object.getClass(); /** * 获取到所有的属性 * */ Field[] fields=clazz.getDeclaredFields(); /** * 对得到的属性进行遍历 * */ for (Field field:fields) { //初始化接口 ViewById viewbyid=field.getAnnotation(ViewById.class); //做一个容错的判断 if (viewbyid!=null) { //获取到里面的值 int viewid=viewbyid.value(); //通过这个id获取到view View view=finder.findViewById(viewid); /** * 同样的对view进行一个容错判断 * */ if (view!=null) { try { ///兼容私有的和共有的 field.setAccessible(true); ///事件注册 field.set(view,object); } catch (Exception e) { e.printStackTrace(); } } } } } //事件注解 private static void injectEvents(ViewFinder finder, Object object) { } }
这个类里面有传activity的,有传view的,不过,
实现findviewbyid只是需要activity那个就好
实现的流程,首先,从外面传来一个activity,
那个activity传到了兼容方法inject(new ViewFinder finder,Object object)
里面,然后调用的是属性注解,属性注解里面,通过拿到的这个类来new 一个出来,
通过new出来的那个获取到里面所有的属性,然后对其进行一一的遍历,遍历完成后
通过ViewById获取到里面的值,利用辅助类以及获取到的这个值实现获取到view,
最后再用一次动态的注册,里面有两次进行了简单的优化,容错处理。
以及对共有和私有进行了一个优化的处理。
辅助类:
package com.example.baselibrary; /** * Created by 廖成康 on 2017/4/19. */ import android.app.Activity; import android.view.View; /** * * 此类作为ViewUtils的辅助类存在 * */ public class ViewFinder { private Activity mactivity; private View mview; public ViewFinder(View view) { mview=view; } public ViewFinder(Activity activity) { mactivity=activity; } /* * 如果activity为空的话,就用view的方式去寻找 * * */ public View findViewById(int viewId) { return mactivity!=null?mactivity.findViewById(viewId):mview.findViewById(viewId); } }
OK,到现在基本上就结束了这个实现方法。