欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-16 17:26:25
...

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

如何使用呢?

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

相关标签: java 框架