关于 APT 以及遇到的一些问题

2019-10-05  本文已影响0人  码匠

APT

Annotation Processing Tool 注解处理工具

在编译时,扫描处理注解信息

常用于生成代码,如 Dagger , EventBus , Butter Knife , Data Binding 这些库

KAPT

Kotlin Annotation Processing Tool Kotlin 注解处理工具

kapt 的用法详见 官方参考文档

实践

参考 EventBusButter Knife

1. 新建 Module annotation ,类型为 Java Library

build.gradle
apply plugin: 'java-library'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
创建注解
@Retention(RetentionPolicy.CLASS) // 注解保留到字节码文件,即编译期
@Target(ElementType.TYPE)       // 可作用于类、接口(包括注解)、枚举上
public @interface Function {
    String name() default "";
}

2. 新建 Module compiler ,类型为 Java Library

build.gradle
apply plugin: 'java-library'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation project(':annotation')
}

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
创建注解处理器
public class FunctionAnnotationProcessor extends AbstractProcessor {

    private Messager mMessager;

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

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Function.class);
        for (Element element : elements) {
            mMessager.printMessage(Diagnostic.Kind.WARNING, "find element: " + element.getSimpleName());
        }
        return false;
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> types = new LinkedHashSet<>();
        types.add(Function.class.getName());
        return types;
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latest();
    }
}
添加 SPI (Service Provider Interface) 配置文件

3. 在 Application Module 中使用注解

build.gradle
    ...
dependencies {
    ...
    implementation project(':annotation')
    annotationProcessor project(':compiler')
}
添加注解到类上
@Function(name = "Home")
public class HomeActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
    }
}
点击 Make Project ,执行编译

可以看到 Build Output 出现以下输出

扩展

使用 Google 的 auto-service 库简化 SPI 配置文件操作

compiler module 的 build.gradle 添加依赖
compileOnly 'com.google.auto.service:auto-service:1.0-rc4'
annotationProcessor 'com.google.auto.service:auto-service:1.0-rc4'
FunctionAnnotationProcessor 类添加注解
@AutoService(Processor.class)
public class FunctionAnnotationProcessor extends AbstractProcessor {
    ...
}
删除 resources 目录
执行 Build -> Rebuild Project 操作

依然可以看到输出

find element: HomeActivity

使用 Kotlin 编写

需要在 build.gradle 中添加 Kotlin 依赖,并使用 kapt 替换 annotationProcessor

Module compilerbuild.gradle 文件如下

apply plugin: 'java-library'
apply plugin: 'kotlin'
apply plugin: 'kotlin-kapt'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation project(':annotation')
    compileOnly 'com.google.auto.service:auto-service:1.0-rc4'
    kapt 'com.google.auto.service:auto-service:1.0-rc4'
}

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
Application Module 如果使用注解的类是 Kotlin 编写,则需要在 build.gradle 同样使用 kapt 替换 annotationProcessor ,否则处理器扫描不到该类
    ...
dependencies {
    ...
    implementation project(':annotation')
    kapt project(':compiler')
}

遇到的一些问题

1. 编译警告 Incremental annotation processing requested

原因

这是 Kotlin 1.3.50 的 bug,自 1.3.31 起,kapt 支持增量注解处理,详见官方文档增量编译

解决方法

2. 编译警告 unknown enum constant AnnotationTarget.XXX

原因

混编,编译时找不到 Kotlin 的类

解决方法

添加 Kotlin 依赖

dependencies {
    ...
    implementation"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

3. 提示 Kotlin not configured

原因

没添加 Kotlin 依赖

解决方法

build.gradle 中添加依赖

dependencies {
    ...
    implementation"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

4. 编译错误 error: cannot find symbol class XXX

原因

没使用 Kotlin 插件

解决方法

build.gradle 中添加插件

apply plugin: 'kotlin'

5. Build Output 没有打印注解处理器的信息

原因

处理器使用 Kotlin 编写,而 build.gradle 中使用 annotationProcessor

解决方法

使用 kapt 替换 annotationProcessor

6. 编译错误 Annotation processors must be explicitly declared now

原因

注解的定义和处理器在同一个module中

解决方法

源码查看

Github地址

参考链接

  1. Android注解&APT技术
  2. Kotlin编译警告问题
  3. Android模拟ButterKnife BindView注解实现绑定view
上一篇 下一篇

猜你喜欢

热点阅读