今天这个小框架的功能跟xutils的一样,通过注解的方式,让我们不用在使用findviewById,以及new OnClickListener。其实他的实现原理,就都是利用的反射和注解来实现。
这里我们先了解一下注解
元注解:
- @Target
- @Retention
- @Documented
- @Inherited
@Target
Target –目标,把…作为目标
顾名思义,他的作用就是:被描述的注解可以用在什么地方,也就是说该注解的使用范围。
看下例子:
//表示该注解只能用在属性上,如果放在其他地方就会报错
@Target(ElementType.FIELD)
public @interface Test {
}

@Target的取值(ElementType.XXX)
- CONSTRUCTOR:用于描述构造方法
- FIELD:用于描述属性
- LOCAL_VARIABLE:用于描述局部变量
- METHOD:用于描述方法
- PACKAGE:用于描述包
- PARAMETER:用于描述参数
- TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention
Retention 保留
意思是说,在什么时候得以保留该Annotation,换句好理解话就是说,被描述的注解在什么时间内有效,是在运行时?编译时?还是什么时候。
- SOURCE:在源文件中有效(即源文件保留)
- CLASS:在class文件中有效(即class保留)
- RUNTIME:在运行时有效(即运行时保留)


这个就表示,该注解的使用范围是在方法上,在源文件中才有效。
@Documented
Documented  备有证明文件的
这个注解什么意思呢?就是说用了这个注解,当你使用javadoc工具处理的时候,会把该注解信息也包括在生成的文档中。
@Documented
public @interface Test_Documented {
   String doTestDocument();
}
public class TestAnnotations {
   public static void main(String arg[]) {
    doSomeTestRetention();
     doSomeTestDocumented();
   }
    public void doSomeTestRetention() {
   }
   @Test_Documented(doTestDocument="Hello document")
   public void doSomeTestDocumented() {
   }
}

@Inherited
Inherited 遗传的 通过继承得到的
这个注解的意思,注解在类上面时,子类会自动继承此注解,否则的话,子类不会继承此注解,该注解只对类有效,对接口,方法属性均无效。
这里有篇文章说的很详尽:
http://blog.csdn.net/snow_crazy/article/details/39381695
当然写这个框架除了注解之外,还需要反射的知识点,这里只简单说明一下,具体详细的内容以后单开一篇。
反射机制获取类有三种方法
我们以MyTestBean为例
public class MyTestBean {
    String name;
    int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
//第一种方式:
//所有的Java对象都有getClass方法。
MyTestBean textView=new MyTestBean(this);
Class<? extends MyTestBean> aClass = myTestBean.getClass();
//第二种方式
//java中每个对象都有class属性
 Class<MyTestBean> aClass = MyTestBean.class;
//第三种方法,通过完整的类名来获取类
Class<?> aClass2 = Class.forName("test.com.duanzi.ui.MyTestBean");
反射机制获取该类的属性和方法
        //获取的方法
        try {
            MyTestBean myTestBean=new MyTestBean();
            myTestBean.setName("周杰伦");
            Class<? extends MyTestBean> aClass = myTestBean.getClass();
            Method getName = aClass.getDeclaredMethod("getName", new Class<?>[]{});
            String name = (String) getName.invoke(myTestBean, new Object[]{});
            Log.d("AAA",name);
        } catch (Exception e) {
            e.printStackTrace();
        }
//获取该类的属性
try {
            MyTestBean myTestBean=new MyTestBean();
            myTestBean.setAge(30);
            Class<? extends MyTestBean> aClass = myTestBean.getClass();
            Field ageField = aClass.getDeclaredField("age");
            ageField.setAccessible(true);//暴力反射。访问私有属性
            int age  = (int) ageField.get(myTestBean);
            Log.d("AAA",age+"岁");
        } catch (Exception e) {
            e.printStackTrace();
        }
热身准备完毕,下面我们开始正式动工。
涉及下面四个类

先定义两个注解
OnClick 点击的注解
/**
 * view点击的注解Annotation
 * 位置在方法上
 * 运行时起作用
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClick {
    int [] value();
}
ViewId 查找id的注解
/**
 * view的注解Annotation
 * 位置在属性上
 * 运行时
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewId {
    int value();
}
public class ViewUtils {
    public static void init(Activity activity){
        init(new ViewFinder(activity),activity);
    }
    public static void init(View view){
        init(new ViewFinder(view),view);
    }
    public static void init(View view,Object o){
        init(new ViewFinder(view),o);
    }
    /**
     * 为了兼容
     * @param finder
     * @param o
     */
    private static void init(ViewFinder finder,Object o){
        //事件监听
        initEvent(finder,o);
        //属性监听
        initField(finder,o);
    }
    private static void initField(ViewFinder finder, Object o) {
        Class<?> aClass = o.getClass();
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            //获取属性上面的注解
            ViewId annotation = field.getAnnotation(ViewId.class);
            if(annotation!=null){
                int viewId = annotation.value();
                //通过注解上的value值获取view
                View view = finder.findViewById(viewId);
                if(view!=null){
                    try {
                        field.set(o,view);//设置属性
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    private static void initEvent(ViewFinder finder, Object o) {
        Class<?> aClass = o.getClass();
        Method[] methods = aClass.getDeclaredMethods();
        for (Method method : methods) {
            method.setAccessible(true);
            OnClick annotation = method.getAnnotation(OnClick.class);
            if(annotation!=null){
                int[] values = annotation.value();
                for (int value : values) {
                    View view = finder.findViewById(value);
                    if(view!=null){
                        //点击时间
                        view.setOnClickListener(new DeclaredClickListener(method,o));
                    }
                }
            }
        }
    }
    public static class DeclaredClickListener implements View.OnClickListener{
        private final Method method;
        private final Object o;
        public DeclaredClickListener(Method method, Object o) {
            this.method = method;
            this.o = o;
        }
        @Override
        public void onClick(View v) {
            try {
                method.invoke(o,v);
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    method.invoke(o,new Object[]{});//不传值走这个
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
}
ViewFinder 辅助类
    private Activity mActivity;
    private View mView;
    public ViewFinder(Activity activity) {
        mActivity = activity;
    }
    public ViewFinder(View view) {
        mView = view;
    }
    public View findViewById(int id){
        return mActivity==null?mView.findViewById(id):mActivity.findViewById(id);
    }
使用方法
//查找属性
  @ViewId(R.id.left_iv)
 private ImageView imageView;
//在Activity的onCreat方法中调用
 protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());
        ViewUtils.init(this);
    }
 //点击事件,第一种方式无参
  @OnClick(R.id.left_iv)
    public void test(){
    }
     //点击事件,第二种方式有参
    @OnClick({R.id.left_iv,R.id.left_tv})
    public void test(View v){
        switch (v.getId()){
            case R.id.left_iv:
                break;
            case R.id.left_tv:
                break;
        }
    }
