Android 注解之使用

145 阅读1分钟

一.先建立注解的模块

  1. 新建立annotation的module image.png

image.png

  1. app中引入module

image.png

image.png

image.png

建立annotation_compiler

image.png

然后在annotation_compiler中的builder中修改

plugins {
    id 'java-library'
}


dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    //3.4+<
    annotationProcessor 'com.google.auto.service:auto-service:1.0-rc4'
    compileOnly 'com.google.auto.service:auto-service:1.0-rc3'

    //3.4-
//    implementation 'com.google.auto.service:auto-service:1.0-rc1'
    implementation project(path: ':annotation')
}

sourceCompatibility = "7"
targetCompatibility = "7"

按照如上操作 app中引入annotation_complier模块

之后在app的builder中修改

image.png

annotationProcessor project(path: ':annotation_compiler')

之后在annotation_complier中建立annotationComplier文件 运用了apt技术 在编译到javac是时候就可以生成我们需要的文件 具体代码如下

image.png

package com.example.annotation_complier;

import com.example.annotation.BindView;
import com.google.auto.service.AutoService;

import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;

/**
 * 注解处理器,用来生成代码的
 * 使用前需要注册
 */
@AutoService(Processor.class)
public class AnnotationsCompiler extends AbstractProcessor {
    //1.支持的版本
    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();
    }

    //2.能用来处理哪些注解
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> types = new HashSet<>();
        types.add(BindView.class.getCanonicalName());
//        types.add(Override.class.getCanonicalName());
        return types;
    }

    //3.定义一个用来生成APT目录下面的文件的对象
    Filer filer;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        filer = processingEnvironment.getFiler();
    }


    /**
     * 所有的坏事都在这个方法中实现
     *
     * @param set
     * @param roundEnvironment
     * @return
     */
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {


        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,"---------------"+set);
        //获取APP中所有用到了BindView注解的对象
        Set<? extends Element> elementsAnnotatedWith = roundEnvironment.getElementsAnnotatedWith(BindView.class);

//        TypeElement//类
//        ExecutableElement//方法
//          VariableElement//属性
        //开始对elementsAnnotatedWith进行分类
        Map<String, List<VariableElement>> map = new HashMap<>();
        for (Element element : elementsAnnotatedWith) {
            VariableElement variableElement = (VariableElement) element;
            String activityName = variableElement.getEnclosingElement().getSimpleName().toString();
            Class aClass = variableElement.getEnclosingElement().getClass();
            List<VariableElement> variableElements = map.get(activityName);
            if (variableElements == null) {
                variableElements = new ArrayList<>();
                map.put(activityName, variableElements);
            }
            variableElements.add(variableElement);
        }


        //开始生成文件
//        package com.example.butterknife_framework_demo;
//        import com.example.butterknife_framework_demo.IBinder;
//        public class MainActivity_ViewBinding implements IBinder<com.example.butterknife_framework_demo.MainActivity> {
//            @Override
//            public void bind(com.example.butterknife_framework_demo.MainActivity target) {
//                target.textView = (android.widget.TextView) target.findViewById(2131165359);
//
//            }
//        }
        if (map.size() > 0) {
            Writer writer = null;
            Iterator<String> iterator = map.keySet().iterator();
            while (iterator.hasNext()) {
                String activityName = iterator.next();
                List<VariableElement> variableElements = map.get(activityName);
                //得到包名
                TypeElement enclosingElement = (TypeElement) variableElements.get(0).getEnclosingElement();
                String packageName = processingEnv.getElementUtils().getPackageOf(enclosingElement).toString();
                try {
                    JavaFileObject sourceFile = filer.createSourceFile(packageName + "." + activityName + "_ViewBinding");
                    writer = sourceFile.openWriter();
                    //        package com.example.dn_butterknife;
                    writer.write("package " + packageName + ";\n");
                    //        import com.example.dn_butterknife.IBinder;
                    writer.write("import " + packageName + ".IBinder;\n");
                    //        public class MainActivity_ViewBinding implements IBinder<
                    //        com.example.dn_butterknife.MainActivity>{
                    writer.write("public class " + activityName + "_ViewBinding implements IBinder<" +
                            packageName + "." + activityName + ">{\n");
                    //            public void bind(com.example.dn_butterknife.MainActivity target) {
                    writer.write(" @Override\n" +
                            " public void bind(" + packageName + "." + activityName + " target){");
                    //target.tvText=(android.widget.TextView)target.findViewById(2131165325);
                    for (VariableElement variableElement : variableElements) {
                        //得到名字
                        String variableName = variableElement.getSimpleName().toString();
                        //得到ID
                        int id = variableElement.getAnnotation(BindView.class).value();
                        //得到类型
                        TypeMirror typeMirror = variableElement.asType();
                        writer.write("target." + variableName + "=(" + typeMirror + ")target.findViewById(" + id + ");\n");
                    }

                    writer.write("\n}}");

                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (writer != null) {
                        try {
                            writer.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }


        return false;
    }
}

注解处理器写完之后 对外使用建立一个窗口 建立JettButterknife文件

image.png

package com.example.zhujie;

import android.app.Activity;

public class JettButterknife {
    public static void bind(Activity activity){
        String name=activity.getClass().getName()+"_ViewBinding";
        try{
            Class<?> aClass=Class.forName(name);
            IBinder iBinder=(IBinder)aClass.newInstance();
            iBinder.bind(activity);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

在MainActivity中如下使用

package com.example.zhujie;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.TextView;

import com.example.annotation.BindView;

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.textMv) // 绑定id
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        JettButterknife.bind(this);
        textView.setText("注解");
    }
}

demo