Annotation processing at compile time:

The core of compile-time annotations relies on the Annotation Processing Tools (APT) implementation. The principle is that after adding annotations, the compiler will check the Subclass of AbstractProcessor at compile time and call the process function of this type, which can be processed in this method.

1. Define custom annotations. Create a New Java Library called Annolib and define a custom annotation

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.FIELD)
public @interface BindView {
    int id();
}
Copy the code

Define annotation handlers. Create a new Java Library that defines an annotation Processor named Processor:

@AutoService(javax.annotation.processing.Processor.class)
@SupportedAnnotationTypes({"example.mydemo.com.annolib.Person"})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class Processor extends AbstractProcessor{

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) { ..... }}Copy the code
  • @autoService (processor. class), which is used to automatically generate meta-INF information for JAVA Processor. Easy to register annotation handlers
  • SupportedAnnotationTypes({}) {SupportedAnnotationTypes({}) {SupportedAnnotationTypes({}); But can be by getSupportedAnnotationTypes method to deal with
  • SupportedSourceVersion(SourceVersion.RELEASE_7) : indicates the supported source code version. But can be by getSupportedSourceVersion method to deal with.
  • The process() method is implemented in two steps: (1) Collect all custom annotated classes in a Class; (2) Generate.java source files. You can use the JavaPoet open source library to write for efficiency.

The subclasses of Element are:

  • ExecutableElement: A method, constructor, or initializer (static or instance) that represents a class or interface, including annotation type elements. Corresponding @ Target (ElementType METHOD) @ Target (ElementType. CONSTRUCTOR)

  • PackageElement; Represents a package element. Provides access to information about packages and their members. Corresponding @ Target (ElementType. PACKAGE)

  • TypeElement; Represents a class or interface program element. Provides access to information about types and members. For @target (elementType.type) note: An enumeration TYPE is a class, while an annotation TYPE is an interface.

  • TypeParameterElement; A type parameter representing a generic class, interface, method, or constructor element. Corresponding @ Target (ElementType PARAMETER)

  • VariableElement; Represents a field, enum constant, method or constructor parameter, local variable, or exception parameter. Corresponding @ Target (ElementType LOCAL_VARIABLE)

Processor Processor

@AutoService(javax.annotation.processing.Processor.class)
@SupportedAnnotationTypes({"example.mydemo.com.annolib.BindView"}) @supportedSourceversion (SourceVersion.release_7) public class Processor extends AbstractProcessor{/** * Specifies the supported Java version, * @return
     */
    @Override
    public SourceVersion getSupportedSourceVersion() {
        returnSourceVersion.latestSupported(); } /** * specifies which annotations the processor needs to process * @returnannotatedset
     */
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> type = new LinkedHashSet<>();
        type.add(BindView.class.getCanonicalName());
        return type; } /** * annotator core code,return falseIs not doing anythingset
     * @param roundEnvironment
     * @return
     */
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) { Messager messager = processingEnv.getMessager(); // Get the element Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(BindView.class); // Iterate over all annotated program elementsfor(Element element : elements) { ElementKind kind = element.getKind(); // Determine if the element is a fieldif(kind == elementkind. FIELD) {// Output messager.printMessage(diagnostic.kind. NOTE,"field:"+ element.toString()); }}return true; }}Copy the code

build.gradle:

apply plugin: 'java-library'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'] // Implement project()':Annolib') // For generating.java source file implementation'com. Squareup: javapoet: 1.11.1'// Used to automatically generate meta-INF information for JAVA Processor. compileOnly'com. Google. Auto. Services: auto - service: 1.0 rc4'
}

sourceCompatibility = "1.7"
targetCompatibility = "1.7"
Copy the code
  • https://github.com/square/javapoet is convenient to generate Java files

(1) Build. Gradle:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com. Android. Support: appcompat - v7:27.1.1'
    implementation 'com. Android. Support. The constraint, the constraint - layout: 1.1.0'// Implementation project(':Annolib'AnnotationProcessor project(annotationProcessor)':processor')}Copy the code

AnnotationProcessor only relies on the annotationProcessor’s library at compile time, not packaged into APK.

(2) Use of annotations:

 @BindView(id = R.id.tv_title)
 TextView mTextView;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);

 }
Copy the code

Build the project with the command./gradlew build, which outputs the Id of the View annotation:

Common annotations in Android

Dependencies: In build.gradle add:

implementation 'com. Android. Support: support - annotations: 27.1.1'   
Copy the code

The official document: https://developer.android.com/reference/android/support/annotation/package-summary 1, the method of parameter @ NonNull statement can not be empty

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    String name = null;
    initView(name);
}
private void initView(@NonNull String s) {
   
}
Copy the code

The @nullable annotation indicates that a method argument or return value can be Null

 private void initView(@Nullable String s) {

    }
Copy the code

The @stringres annotation indicates that a resource ID of type String is required

 private void initView(@StringRes int strId) {

    }
Copy the code

4. @idres indicates that a resource ID is required

private void initView(@IdRes int id) {

    }
Copy the code

@intdef instead of enumeration:

public static final int ONE = 1;
public static final int TWO = 2;
public static final int THREE = 3;

@IntDef({ONE, TWO, THREE})
public @interface Common{

}

public void setValue(@Common int value) {

}


private void initView() {
    setValue(ONE);
}
Copy the code