自定义一个Java运行时注解框架

来源:互联网 发布:淘宝邮编怎么看 编辑:程序博客网 时间:2024/06/13 15:40

随着项目开发经验的累计,逐渐接触到很多成熟的注解框架(ButterKnife,Retrofit等等),框架是为了减少人力成本,所以框架就会要求计算机去做一些人不想做的重复劳动的工作(比如findViewById),注解框架分为编译时注解和运行时注解

编译时框架:编译的时候耗时,但是不影响运行效果

运行时框架:编译速度不会影响但是会影响运行效果

其实超大项目才会考虑到运行时和编译时的效率问题,小型demo反射注解框架的耗时对性能的消耗几乎为0,一句话总结就是如果你对反射注解理解的不深刻,请不要在公司项目上使用

/** * @Description: * @Author: Liangchaojie * @Create On 2017/12/8 10:17 */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface BindView {    @IdRes int value();}
/** * @Description: * @Author: Liangchaojie * @Create On 2017/12/8 10:19 */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface Onclick {    @IdRes int[] value();}
package com.test.inject;import android.app.Activity;import android.content.Context;import android.os.Build;import android.util.Log;import android.view.View;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.HashMap;/** * @Description: * @Author: Liangchaojie * @Create On 2017/12/8 10:20 */public class Injector {    public static void init(Activity context){        inject(context,context.getWindow().getDecorView());    }    private static void inject(Activity context, View decorView) {        Class c = context.getClass();        if(c==null) return;        HashMap<Integer, View> viewHashMap = new HashMap<>();        Field[] fields = c.getDeclaredFields();        Method[] methods = c.getDeclaredMethods();        for(Field field:fields){            if(field.isAnnotationPresent(BindView.class)){                field.setAccessible(true);                int viewId=field.getAnnotation(BindView.class).value();                View view = decorView.findViewById(viewId);                try {                    field.set(context,view);                } catch (IllegalAccessException e) {                    e.printStackTrace();                }                viewHashMap.put(viewId, view);            }        }        for (Method method:methods){            if(method.isAnnotationPresent(Onclick.class)){                method.setAccessible(true);                int[] values = method.getAnnotation(Onclick.class).value();                for(int i:values){                    if(viewHashMap.containsKey(i)){                         viewHashMap.get(i).setOnClickListener(new Click(method,context));                    }                }            }        }    }    private static class Click implements View.OnClickListener{        private Method method;        private Context context;        public Click(Method method, Activity context) {            this.method = method;            this.context = context;        }        private void checkParam(View v) {            Class<?>[] parameterTypes = method.getParameterTypes();            try {                if(parameterTypes.length==0){                    method.invoke(context);                }                if(parameterTypes.length>1 ){                    throw new IllegalArgumentException("最多只能有一个参数!");                }                if(parameterTypes.length==1){                    method.invoke(context, v);                }            } catch (IllegalAccessException e) {                e.printStackTrace();            } catch (InvocationTargetException e) {                e.printStackTrace();            }        }        @Override        public void onClick(View v) {            checkParam(v);        }    }}

如何使用呢?

这里写图片描述