Annotation in Java is a very amazing thing, especially now there are many Android libraries that are implemented by annotation.
We don't talk about annotations that are processed at Runtime through reflection, but rather at Compile time. Let's start with Java annotation processor.
Simple practice:
1. Create annotation
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.CLASS) public @interface MethodProcessor { String name() default "Method"; }
Then we can use it
@MethodProcessor(name = "Method") public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
2. Annotation processor
The above is just about how to use it. Actually, we don't know how the interior is generated yet. Let's look down.
//@AutoService(Processor.class)? This is an annotation processor developed by Google, //Used to generate the META-INF/services/javax.annotation.processing.Processor file. //Import method compile 'com. Google. Auto. Service: Auto Service: 1.0-rc2' @AutoService(Processor.class) public class MyProcessor extends AbstractProcessor { private Types mTypeUtils; private Elements mElementUtils; private Filer mFiler; private Messager mMessager; @Override public Set<String> getSupportedAnnotationTypes() { Set<String> annotations = new LinkedHashSet<>(); //Add our own defined comments annotations.add(MethodProcessor.class.getCanonicalName()); return annotations; } @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); } @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); mTypeUtils = processingEnv.getTypeUtils(); mElementUtils = processingEnv.getElementUtils(); mFiler = processingEnv.getFiler(); mMessager = processingEnv.getMessager(); } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { // //Traverse all annotated elements for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(MethodProcessor.class)) { if (annotatedElement.getKind() != ElementKind.CLASS) { error(annotatedElement, "Only classes can be annotated with @%s", MethodProcessor.class.getSimpleName()); return true; } // //Parse and generate code analysisAnnotated(annotatedElement); } return false; } private void error(Element e, String msg, Object... args) { mMessager.printMessage(Diagnostic.Kind.ERROR, String.format(msg, args), e); } private static final String SUFFIX = "Test"; private static final String packageName = "com.company.processtest"; private static final String retStr = ""; private void analysisAnnotated(Element classElement) { MethodProcessor annotation = classElement.getAnnotation(MethodProcessor.class); String name = annotation.name(); String newClassName = name + SUFFIX; StringBuilder builder = new StringBuilder() .append("package " + packageName + ";\n\n") .append("public class ") .append(newClassName) .append(" {\n\n") // open class .append("\tpublic String getMessage() {\n") // open method .append("\t\treturn \""); // this is appending to the return statement builder.append(retStr).append(" !\\n"); builder.append("\";\n") // end return .append("\t}\n") // close method .append("}\n"); // close class try { // write the file JavaFileObject source = mFiler.createSourceFile(packageName + "." + newClassName); Writer writer = source.openWriter(); writer.write(builder.toString()); writer.flush(); writer.close(); } catch (IOException e) { } } }
Finally, build the project and generate the final java file
File location: ProcessTest\app\build\generated\source\apt\debug\com\company\processtest\MethodTest.java
package com.company.processtest; public class MethodTest { public String getMessage() { return "this is just a test !\n"; } }
In this way, you can use this class
@MethodProcessor(name = "Method") public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MethodTest test = new MethodTest(); test.getMessage(); } }
Note: the annotation class and AbstractProcessor must create a new java library.
Generate java classes in AbstractProcessor, which can be written using open source java Poe library to improve efficiency