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

随着项目开发经验的累计,逐渐接触到很多成熟的注解框架(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 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);
        }
    }
}

如何使用呢?

自定义一个Java运行时注解框架_第1张图片

你可能感兴趣的:(Android,java,框架)