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

前言: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,到现在基本上就结束了这个实现方法。













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值