apt-注解开发-3-自定义processor

来源:互联网 发布:关于网络的流行语 编辑:程序博客网 时间:2024/04/29 07:56

自定义processor

  • [0]创建一个java module 命名为apt 在gradle中引入
apply plugin: 'java'dependencies {    compile fileTree(include: ['*.jar'], dir: 'libs')    compile 'com.google.auto.service:auto-service:1.0-rc2'    compile 'com.squareup:javapoet:1.7.0'    compile project(':annotation')//定义的注解 用于搜索该项目中定义的注解    sourceCompatibility = 1.7    targetCompatibility = 1.7}
  • [1]定义注解信息类 方便处理注解元素
public class BindViewField {    //可用的注解元素    private VariableElement variableElement;    //view的id 我们自己的id    private int mResId;    public BindViewField(Element element) {        if (element.getKind()!= ElementKind.FIELD){        //在定义注解时 我们限制的 @Target(ElementType.FIELD)            throw new IllegalArgumentException(                    "\"Only fields can be annotated with @%s\",\n" +                    "                    BindView.class.getSimpleName())");        }        variableElement = (VariableElement) element;        //解析注解类 获取注解信息        LzfBindView bindView=variableElement.getAnnotation(LzfBindView.class);        mResId=bindView.value();        <!--        @Target(ElementType.FIELD)        @Retention(RetentionPolicy.CLASS)        public @interface LzfBindView {         int value();//既是这里的value view的id        }        -->        if (mResId<0){            throw new IllegalArgumentException( String.format("value() in %s for field %s is not valid !", LzfBindView.class.getSimpleName(),                    variableElement.getSimpleName()));        }    }    /**     * 获取变量名称     *     * @return     */    Name getFieldName() {        return variableElement.getSimpleName();    }    /**     * 获取变量id     *     * @return     */    int getResId() {        return mResId;    }    /**     * 获取变量类型     *     * @return     */    TypeMirror getFieldType() {        return variableElement.asType();    }}

-[2]定义文件创建的规则

public class AnnotationUtils {    private static class TypeUtil{    //包名 类名        static final ClassName BINDER=ClassName.get("lzf.api","ViewBinder");        static final ClassName FINDER=ClassName.get("lzf.api","ViewFinder");    }    private TypeElement typeElement;//获取类型    private ArrayList<BindViewField> mFields;//注解元素    private Elements elements;    public AnnotationUtils(TypeElement typeElement, Elements elements) {        this.typeElement = typeElement;        this.elements = elements;        mFields=new ArrayList<>();    }    void addField(BindViewField field){        mFields.add(field);    }    JavaFile generateFile(){        //生成方法        MethodSpec.Builder bindViewMethod = MethodSpec.methodBuilder("bindView")                .addModifiers(Modifier.PUBLIC)//方法权限                .addAnnotation(Override.class)//给方法添加注解                .addParameter(TypeName.get(typeElement.asType()), "host")//方法内参数类型 参数名称                .addParameter(TypeName.OBJECT, "source")                .addParameter(TypeUtil.FINDER, "finder");        for (BindViewField field : mFields) {            // find views            bindViewMethod.addStatement("host.$N = ($T)(finder.findView(source, $L))", field.getFieldName(), ClassName.get(field.getFieldType()), field.getResId());        }        //解绑        MethodSpec.Builder unBindViewMethod = MethodSpec.methodBuilder("unBindView")                .addModifiers(Modifier.PUBLIC)                .addParameter(TypeName.get(typeElement.asType()), "host")                .addAnnotation(Override.class);        for (BindViewField field : mFields) {            unBindViewMethod.addStatement("host.$N = null", field.getFieldName());        }        //generaClass 创建类        TypeSpec injectClass = TypeSpec.classBuilder(typeElement.getSimpleName() + "$$ViewBinder")//类名                .addModifiers(Modifier.PUBLIC)//类修饰符                .addSuperinterface(ParameterizedTypeName.get(TypeUtil.BINDER, TypeName.get(typeElement.asType())))//实现的接口 泛型参数类型                .addMethod(bindViewMethod.build())                .addMethod(unBindViewMethod.build())                .build();        String packageName = elements.getPackageOf(typeElement).getQualifiedName().toString();//文件目录        return JavaFile.builder(packageName, injectClass).build();    }}

-[3]自定义processor

@AutoService(Processor.class)public class MyClassProcessor extends AbstractProcessor {    private Filer filer;//文件操作类    private Elements elements;    private Messager messager;    private Map<String,AnnotationUtils> annotationUtilsMap;    @Override    public synchronized void init(ProcessingEnvironment processingEnv) {        super.init(processingEnv);        filer=processingEnv.getFiler();        elements=processingEnv.getElementUtils();        annotationUtilsMap=new TreeMap<>();    }    @Override    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {        annotationUtilsMap.clear();        //获取注解信息        processBindView(roundEnv);        for (AnnotationUtils annotationUtils:annotationUtilsMap.values()) {            try {            //将所有的注解工具类都写成文件            //多个activity都有注解使用 会产生多个注解工具类  每个工具类将生成一个文件                annotationUtils.generateFile().writeTo(filer);            } catch (IOException e) {                e.printStackTrace();                error("Generate file failed, reason: %s", e.getMessage());            }        }       return true;    }    private void processBindView(RoundEnvironment environment){        for (Element e : environment.getElementsAnnotatedWith(LzfBindView.class)) {        //environment.getElementsAnnotatedWith(LzfBindView.class)        //获取所有lzfbindview注解的元素        //创建注解工具类            AnnotationUtils annotationUtils=getAnnotationUtils(e);            //获取注解元素信息            BindViewField bindViewField=new BindViewField(e);            //将注解信息添加到注解工具类            annotationUtils.addField(bindViewField);        }    }    private AnnotationUtils getAnnotationUtils(Element e){        TypeElement typeElement= (TypeElement) e.getEnclosingElement();        String fullName=typeElement.getQualifiedName().toString();        AnnotationUtils annotationUtils=annotationUtilsMap.get(fullName);        if (annotationUtils==null){            annotationUtils=new AnnotationUtils(typeElement,elements);            annotationUtilsMap.put(fullName,annotationUtils);        }        return annotationUtils;    }    private void error(String msg, Object... args) {        messager.printMessage(Diagnostic.Kind.ERROR, String.format(msg, args));    }    @Override    public SourceVersion getSupportedSourceVersion() {        return SourceVersion.latestSupported();    }    @Override    public Set<String> getSupportedAnnotationTypes() {        Set<String> types=new LinkedHashSet<>();        types.add(LzfBindView.class.getCanonicalName());        return types;    }}

感谢

http://www.cnblogs.com/whoislcj/p/6168641.html