打造自己的IOC注解框架------findViewById

来源:互联网 发布:单片机romram图片 编辑:程序博客网 时间:2024/05/24 07:07
前言: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,到现在基本上就结束了这个实现方法。













0 0
原创粉丝点击