最近在研究注解看了刘望舒大大的编译时注解处理器,按步骤操作,make project的时候突然掉坑里了,如下图
场景还原:
1.定义注解
这里首先在项目中new module->java or Kotlin Library来专门存放注解,这个Library名为annotations。接下来定义注 解,如下所示:
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.FIELD)
public @interface BindView {
int value() default 1;
}
2.编写注解处理器
接着在项目中new module->java or Kotlin Library来专门存放注解,这个Library名为processor。配置下processor库的build.gradle:
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(":annotations")
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
接下来编写注解处理器ClassProcessor,它继承AbstractProcessor,如下所示:
package com.ljp.laucher.processor;
import com.ljp.laucher.annotations.BindView;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
public class ClassProcessor extends AbstractProcessor {
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
//被注解处理工具调用,并输入 ProcessingEnviroment 参数。
// ProcessingEnviroment提供很多有用的 工具类,
// 比如Elements、Types、Filer和Messager等。
super.init(processingEnv);
}
@Override
public boolean process(Set< ? extends TypeElement > annotations, RoundEnvironment roundEnv) {
//相当于每个处理器的主函数main(),在这里写你的扫描、评估和处理注解的代码,
// 以及生 成Java文件。输入参数RoundEnviroment,可以让你查询出包含特定注解的被注解元素。
Messager messager = processingEnv.getMessager();
for (Element element : roundEnv.getElementsAnnotatedWith(BindView.class)) {
if (element.getKind() == ElementKind.FIELD) {
messager.printMessage(Diagnostic.Kind.NOTE, "printMessage:" + element.toString());
}
}
return false;
}
@Override
public Set< String > getSupportedAnnotationTypes() {
//这是必须指定的方法,指定这个注解处理器是注册给哪个注解的。
// 注 意,它的返回值是一个字符串的集合,包含本处理器想要处理的注解类型的合法全称。
Set< String > annotataions = new LinkedHashSet<>();
annotataions.add(BindView.class.getCanonicalName());
return annotataions;
}
@Override
public SourceVersion getSupportedSourceVersion() {
//用来指定你使用的 Java 版本,通常这里返回 SourceVersion.latestSupported()。
return SourceVersion.latestSupported();
}
}
3.注册注解处理器
为了能使用注解处理器,需要用一个服务文件来注册它。现在我们就来创建这个服务文件。首先在 processor 库的
main
目录下新建
resources
资源文件夹,接下来在
resources
中再建立
META-INF/services目录 文件夹。最后在
META-INF/services
中创建
javax.annotation.processing.Processor文件,这个文件中的内容是 注解处理器的名称。这里我们的javax.annotation.processing.Processor文件的内容为“
com.ljp.laucher.processor.ClassProcessor”
。
整体代码结构如下所示:
![](https://i-blog.csdnimg.cn/blog_migrate/1bfea962b287e275044f206d2280d9d9.png)
4.应用注解
接下来在我们的主工程项目(
app
)中引用注解。首先要在主工程项目的
build.graldle
中引用
annotations
和
processor
这两个库:
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
//注意千万不要使用implementation,因为这个运行时注解要在运行时生效
//用implementation会使processor和app的build下面生成的classes.dex中都定义了
//com.ljp.laucher.processor.ClassProcessor导致冲突
annotationProcessor project(":processor")
implementation project(":annotations")
}
接下来在
MainActivity
中应用注解,如下所示:
package com.ljp.laucher.testannotation;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import com.ljp.laucher.annotations.BindView;
public class MainActivity extends AppCompatActivity {
@BindView(value = R.id.tv_test_bind_view)
TextView tv_test_bind_view;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
接下来快乐的时光来了,先clean project再make project(Android Studio 4.0的Gradle Console合并到build output中了),运行结果如下