自定义注解自动代码构建


新建javaLib-annotation(自定义注解)

build.gradle

apply plugin: 'java-library'
...

//中文乱码问题(错误:编码GBK不可映射字符)
tasks.withType(JavaCompile) {
    options.encoding = "UTF-8"
}

sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
自定义注解

@Target:注解的作用目标
@Target(ElementType.TYPE)——接口、类、枚举、注解
@Target(ElementType.FIELD)——字段、枚举的常量
@Target(ElementType.METHOD)——方法
@Target(ElementType.PARAMETER)——方法参数
@Target(ElementType.CONSTRUCTOR) ——构造函数
@Target(ElementType.LOCAL_VARIABLE)——局部变量
@Target(ElementType.ANNOTATION_TYPE)——注解
@Target(ElementType.PACKAGE)——包
@Retention:注解的保留位置
RetentionPolicy.SOURCE:这种类型的Annotations只在源代码级别保留,编译时就会被忽略,在class字节码文件中不包含。
RetentionPolicy.CLASS:这种类型的Annotations编译时被保留,默认的保留策略,在class文件中存在,但JVM将会忽略,运行时无法获得。
RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。
@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解

BindViewClass
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface BindViewClass {
    String groupName() default "Widget";//默认值="Widget"

    String value();//无默认值
}

BindFragmentClass
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface BindFragmentClass {
   String value();
}

新建javaLib-processor

build.gradle

apply plugin: 'java-library'

...

dependencies {
    implementation 'com.google.auto.service:auto-service:1.0-rc6'
    annotationProcessor 'com.google.auto.service:auto-service:1.0-rc6'
    implementation 'com.google.auto:auto-common:0.10'
    implementation 'com.squareup:javapoet:1.11.1'
    implementation project(path: ':annotation')
}

//中文乱码问题(错误:编码GBK不可映射字符)
tasks.withType(JavaCompile) {
    options.encoding = "UTF-8"
}

sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
MyProcessor 自定义AbstractProcessor
@SupportedAnnotationTypes({"BindViewClass全路径","BindFragmentClass全路径"})
@AutoService(Processor.class)
public class MyProcessor extends AbstractProcessor {

     private HashMap<String, HashMap<String,Element>> widgets;
    private HashMap<String, Element> fragments;
    private AnnotatedHelper annotatedHelper;


    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        fragments = new HashMap<>();
        widgets = new HashMap<>();
        annotatedHelper = new AnnotatedHelper();
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
       fragments.clear();
        widgets.clear();
        //遍历所有@BindFragmentClass注解
        for (Element element : roundEnvironment.getElementsAnnotatedWith(BindFragmentClass.class)) {
            BindFragmentClass annotation = element.getAnnotation(BindFragmentClass.class);
            fragments.put(annotation.value(), element);
        }
		//遍历所有@BindViewClass注解
        for (Element element : roundEnvironment.getElementsAnnotatedWith(BindViewClass.class)) {
            BindViewClass annotation = element.getAnnotation(BindViewClass.class);
            HashMap<String, Element> elementHashMap = widgets.get(annotation.groupName());
            if (elementHashMap == null){
                elementHashMap = new HashMap<>();
            }
            elementHashMap.put(annotation.value(),element);
            widgets.put(annotation.groupName(), elementHashMap);
        }
          //生成文件
		if (!widgets.isEmpty() || !fragments.isEmpty()) {
            try {
                annotatedHelper.createFile(fragments, widgets).writeTo(processingEnv.getFiler());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> types = new LinkedHashSet<>();
        types.add(BindFragmentClass.class.getCanonicalName());
        types.add(BindViewClass.class.getCanonicalName());//手动高亮划重点  声明要处理的注解
        return types;
    }
}
AnnotatedHelper 辅助生成文件

注 通过ClassName.get("java.lang", "String")设置类型,可自动在文件中导入相关包import java.lang.String;

class AnnotatedHelper {
    private static final TypeVariableName T = TypeVariableName.get("T");//定义泛型

   //生成方法体
  private CodeBlock.Builder getCodeBlock(HashMap<String, Element> map, int type) {
        CodeBlock.Builder codeBlock = CodeBlock.builder();
        codeBlock.beginControlFlow("\tswitch (name)");//这句代码之后添加"{",可单独使用 但建议与"endControlFlow"配对使用
        for (String key : map.keySet()) {
            Element element = map.get(key);
            codeBlock.add("\t\tcase $S: ", key);
            ClassName className = ClassName.get(element.getEnclosingElement().toString(), element.getSimpleName().toString());
            if (type ==1){
                codeBlock.addStatement("return (T) (bundle == null ? new $T() : new $T(bundle))", className, className);//这句执行之后添加";"并换行
            } else {
                codeBlock.addStatement("return (T) (bundle == null ? new $T(parent) : new $T(parent,bundle))", className, className);
            }
        }
        codeBlock.addStatement("\t\tdefault: return null");
        codeBlock.endControlFlow();//这句代码之前添加"}",须有前置"beginControlFlow"配对使用
        return codeBlock;
    }

    JavaFile createFile(HashMap<String, Element> fragments, HashMap<String, HashMap<String, Element>> widgets) {
        //生成方法
        MethodSpec.Builder fragmentMethod = MethodSpec.methodBuilder("getFragmentInstance")
                .addModifiers(Modifier.PUBLIC, Modifier.STATIC)//添加方法修饰信息
                .addTypeVariable(AnnotatedHelper.T)//添加泛型
                .returns(AnnotatedHelper.T)//添加方法返回类型
                .addJavadoc(CodeBlock.builder().add("查找路由表获取fragment对象\n").build())//添加注释
                .addCode(getCodeBlock(fragments,1).build())//添加方法体
                .addParameter(ClassName.get("java.lang", "String"), "name")//添加参数  (类型 参数名)
                .addParameter(ClassName.get("android.os", "Bundle"), "bundle");//添加参数  (类型 参数名)

		//生成方法
        ArrayList<MethodSpec.Builder> groups = null;
        if (widgets != null && !widgets.keySet().isEmpty()) {
            groups = new ArrayList<>();
            for (String key : widgets.keySet()) {
                MethodSpec.Builder widgetMethod = MethodSpec.methodBuilder(String.format("get%sInstance", key))
                        .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
                        .addTypeVariable(AnnotatedHelper.T)
                        .returns(AnnotatedHelper.T)
                        .addCode(getCodeBlock(widgets.get(key),2).build())
                        .addJavadoc(CodeBlock.builder().add("查找路由表获取$S中组件对象\n",key).build())//添加注释
                        .addParameter(ClassName.get("java.lang", "String"), "name")
                        .addParameter(ClassName.get("android.view", "ViewGroup"), "parent")
                        .addParameter(ClassName.get("android.os", "Bundle"), "bundle");
                groups.add(widgetMethod);
            }
        }
		//生成类
        TypeSpec.Builder injectClass = TypeSpec.classBuilder("Factory")//类名
                .addModifiers(Modifier.PUBLIC)//类修饰符
                .addJavadoc(CodeBlock.builder().add("路由表\n").build())//添加注释
//                .addField(FieldSpec  //添加变量
//                        .builder(int.class, "Version", Modifier.STATIC, Modifier.PRIVATE, Modifier.FINAL)
//                        .initializer("$L",1)//初始化变量
//                        .build())
//                .addType(TypeSpec.classBuilder("累不累").build())//添加内部类
//                .addAnnotation(Deprecated.class)//添加注解(方法体和变量同理)
//                .addAnnotation(AnnotationSpec.builder(Target.class)//添加注解(方法体和变量同理)
//                        .addMember("value", "$L.TYPE",ClassName.get("java.lang.annotation", "ElementType"))
//                        .build())
                .addMethod(fragmentMethod.build());//添加方法
        if (groups != null && !groups.isEmpty()) {
            for (MethodSpec.Builder build : groups) {
                injectClass.addMethod(build.build());
            }
        }
        return JavaFile.builder("指定文件包路径", injectClass.build()).build();//在指定包路径生成类文件
    }
}

以上通过JavaFile相关API自动生成文件
以下通过JavaFileObject+字符串写入文件

StringBuilder builder = new StringBuilder()
                .append("package com.***.view;\n\n")
                .append("import android.os.Bundle;\n")
                ...
                .append("}");

        try {
            JavaFileObject source = processingEnv.getFiler().createSourceFile(
                    "指定文件包路径.Factory");
            Writer writer = source.openWriter();
            writer.write(builder.toString());
            writer.flush();
            writer.close();
        } catch (IOException e) {
            //
        }

app模块配置

build.gradle 本人项目中使用了kotlin所以要用kapt,没有kotlin的项目中使用annotationProcessor

apply plugin: 'kotlin-kapt'
...
dependencies {
    kapt project(path: ':processor')
    implementation project(path: ':annotation')
 }

编译后生成的文件

package com.***.view;

import android.os.Bundle;
import android.view.ViewGroup;
import com.***.fragment.HomeFragment;
import com.***.PersonalCentreFragment;
import com.***.SmallAppManagerFragment;
import com.***.WebFragment;
import com.***.BannerVH;
import com.***.DashboardVH;
import com.***.MyAppVH;
import com.***.NotifyVH;
import com.***.WebVH;
import java.lang.String;

public class Factory {
  public static <T> T getFragmentInstance(String name, Bundle bundle) {
     switch (name){
         case "web": return (T) (bundle == null ? new WebFragment() : new WebFragment(bundle));
         case "personalCentre": return (T) (bundle == null ? new PersonalCentreFragment() : new PersonalCentreFragment(bundle));
         case "subApp": return (T) (bundle == null ? new SmallAppManagerFragment() : new SmallAppManagerFragment(bundle));
         case "home": return (T) (bundle == null ? new HomeFragment() : new HomeFragment(bundle));
         default: return null;
    }
     }

  public static <T> T getViewHolderInstance(String name, ViewGroup parent, Bundle bundle) {
     switch (name){
         case "notifyVH": return (T) (bundle == null ? new NotifyVH(parent) : new NotifyVH(parent,bundle));
         case "banner": return (T) (bundle == null ? new BannerVH(parent) : new BannerVH(parent,bundle));
         case "webVH": return (T) (bundle == null ? new WebVH(parent) : new WebVH(parent,bundle));
         case "myApp": return (T) (bundle == null ? new MyAppVH(parent) : new MyAppVH(parent,bundle));
         case "dashboard": return (T) (bundle == null ? new DashboardVH(parent) : new DashboardVH(parent,bundle));
         default: return null;
    }
     }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值