@Target({ElementType.FIELD, ElementType.METHOD})// 作用在什么地方 @Retention(RetentionPolicy.RUNTIME) // 作用范围 public @interface BindView { String value(); int id(); } public enum ElementType { TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE } public enum RetentionPolicy { SOURCE, CLASS, RUNTIME }@IntDef代替枚举
class Test { private static final int SUNDAY = 0; private static final int MonDAY = 1; // 注解代替枚举,可以节省内存空间 @IntDef({SUNDAY, MONDAY}) @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.SOURCE) @interface WeekDay{ } public static void setCurrDay(@WeekDay int currDay) { } public static void main(String[] args) { setCurrDay(SUNDAY); } }APT注解处理器使用
javac 把 java 文件编译成 class 文件,APT就是作用在javac上。
1、新建一个名为 annotation_compiler 的 java library 工程
2、annotation_compiler 工程的 gradle 中添加如下依赖
// 在 java library 的 gradle 文件中添加如下: annotationProcessor 'com.google.auto.service:auto-service:1.0-rc4' compileonly 'com.google.auto.service:auto-service:1.0-rc4'
3、开始注解处理器编码
@AutoService(Processor.class) public class AnnotationsCompiler extends AbstractProcessor { // 1.支持的版本 @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); } // 2.能用来处理哪些注解 @Override public SetAPT实现butterknife实战 1、新建一个 java-library 类型的注解工程 “annotation”getSupportedAnnotationTypes() { // 只能处理 @BindView 类型的注解 Set types = new HashSet<>(); types.add(BindView.class.getCanonicalName()); return types; } // 3.定义一个用来生成APT目录下面的文件的对象 Filer filer; @Override public synchronized void init(ProcessingEnvironment processingEnvironment) { super.init(processingEnvironment); filer = processingEnvironment.getFiler(); } // 4、处理逻辑,生成所需的代码 @Override public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment) { // 日志打印 processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "jett---------------" + set); return false; } }
@Target(ElementType.FIELD) @Retention(RetentionPolicy.SOURCE) public @interface BindView { int value(); }2、新建一个 application 类型工程
public interface IBinder3、目的是在 application 工程的 /build/generated/ap_generated_sources/debug/out/... 路径下生成如下代码:{ void bind(T target); } 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(); } } } public class MainActivity extends AppCompatActivity { @BindView(R.id.tvText) TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); JettButterknife.bind(this); textView.setText("你好"); } } // gradle 文件中添加如下依赖: implementation project(path: ':annotations') annotationProcessor project(path: ':annotation_compiler')
package com.example.dn_butterknife; import com.example.dn_butterknife.IBinder; public class MainActivity_ViewBinding implements IBinder4、因此 APT 工程的代码应该这么编码{ @Override public void bind(com.example.dn_butterknife.MainActivity target) { target.textView = (android.widget.TextView) target.findViewById(2131165359); } }
新建 java-ibrary 类型的 annotation_compiler 工程
package com.example.annotation_compiler; import com.example.annotations.BindView; import com.google.auto.service.AutoService; import com.google.errorprone.annotations.Var; import java.io.Writer; import java.lang.reflect.Type; 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.Messager; 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.ExecutableElement; 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 { Filer filer; @Override public synchronized void init(ProcessingEnvironment processingEnvironment) { super.init(processingEnvironment); filer = processingEnvironment.getFiler(); } @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); } @Override public SetgetSupportedAnnotationTypes() { Set types = new HashSet<>(); types.add(BindView.class.getCanonicalName()); return types; } @Override public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment) { processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "jett---------------" + set); // 1、获取APP中所有用到了BindView注解的对象 Set extends Element> elementsAnnotatedWith = roundEnvironment.getElementsAnnotatedWith(BindView.class); // 2、开始对elementsAnnotatedWith进行分类 // // Element 的子类有如下: // // TypeElement //类 // ExecutableElement //方法 // VariableElement //属性 // Map > map = new HashMap<>(); for (Element element : elementsAnnotatedWith) { // @BindView 是属性类型,所以直接强转 VariableElement variableElement = (VariableElement) element; // 获取 @BindView 所在的作用域,也就是Activity类,拿到Activity的名称 String activityName = variableElement.getEnclosingElement().getSimpleName().toString(); // 获取 @BindView 所在的作用域,也就是Activity类,拿到Activity的字节码对象 Class aClass = variableElement.getEnclosingElement().getClass(); // [ // "MainActivity" : {VariableElement1, VariableElement2, ...} // "TwoActivity" : {VariableElement1, VariableElement2} // "ThreeActivity" : {VariableElement1} // ] List variableElements = map.get(activityName); if (variableElements == null) { variableElements = new ArrayList<>(); map.put(activityName, variableElements); } variableElements.add(variableElement); } // 3、开始生成文件 // // package com.example.dn_butterknife; // import com.example.dn_butterknife.IBinder; // public class MainActivity_ViewBinding implements IBinder { // @Override // public void bind(com.example.dn_butterknife.MainActivity target) { // target.textView = (android.widget.TextView) target.findViewById(2131165359); // } // } // if (map.size() > 0) { Writer writer = null; for (String activityName : map.keySet()) { // 拿到某个 Activity 中的所有注解 List variableElements = map.get(activityName); // 拿到包名 TypeElement enclosingElement = (TypeElement) variableElements.get(0).getEnclosingElement(); String packageName = processingEnv.getElementUtils().getPackageOf(enclosingElement).toString(); try { // 开始生成 MainActivity_ViewBinding.java 文件 // 创建名为 com.example.dn_butterknife.MainActivity 的.java文件 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 // { writer.write("public class " + activityName + "_ViewBinding implements IBinder<" + packageName + "." + activityName + ">{n"); // @Override // public void bind(com.example.dn_butterknife.MainActivity target) { writer.write(" @Overriden" + " 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; } } // 在 gradle 文件中添加如下依赖: // annotationProcessor 'com.google.auto.service:auto-service:1.0-rc4' // compileonly 'com.google.auto.service:auto-service:1.0-rc4'
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)