Android APT 开发实践

基于 APT、JavaPoet,自动生成 Activity/Fragment 对应的 ViewModel.

项目界面需求较特殊,需频繁新增 Activity/Fragment,虽基于 ViewModel、LiveData 的 MVVM 模式已将 View 与 Model 彻底解耦,数据获取及处理逻辑可直接复用,但仍存在一些样板代码。

举个例子,新增一个需要展示用户信息和书籍信息的 MainActivity,那就要新增对应的 ViewModel:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MainActivityViewModel extends ViewModel { 
private UserDataStore mUserDataStore = new UserDataStore();

private BookDataStore mBookDataStore = new BookDataStore();

public UserDataStore getUserDataStore() {
return mUserDataStore;
}

public BookDataStore getBookDataStore() {
return mBookDataStore;
}
}

如何规避编写这样的样板代码呢?想要实现的效果如下,在 MainActivity 中添加注解,列出该界面需使用的 Model:

1
2
3
4
5
@ViewModelAutoGen({
UserDataStore.class,
BookDataStore.class
})
public class MainActivity extends AppCompatActivity {...}

然后 Make Project 编译一下,自动生成 MainActivityViewModel 类,无需手动编写。

而基于 APT、JavaPoet 可以实现这个需求,先简单了解下它们。

APT 即 Annotation Processing Tool,编译时注解处理器,是 javac 的一个工具,用于编译时扫描和处理注解。通过 APT 可以获取到注解和被注解对象的相关信息,在拿到这些信息后我们可以根据需求自动生成一些代码,省去手动编写。获取注解及生成代码在代码编译期完成,相比反射在运行时处理注解大大提高了程序性能。

JavaPoet 是一个辅助生成 Java 源代码的工具库,APT 结合 JavaPoet,可以便捷的生成代码。

下面来看具体如何实现,首先创建一个 java-library ViewModelAnnotation,在其中定义注解:

1
2
3
4
5
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
public @interface ViewModelAutoGen {
Class[] value();
}

然后再创建一个 java-library ViewModelAnnotationProcessor ,在其中处理注解,处理类需继承 AbstractProcessor 并添加特定注解标注,如下:

1
2
3
4
@AutoService(Processor.class)
public class ViewModelAnnotationProcessor extends AbstractProcessor {
...
}

而最关键的代码生成逻辑就在此类中了,代码见 ViewModelAnnotationProcessor.java

外部导入时需通过 annotationProcessor 使其支持编译时注解处理:

1
2
3
4
dependencies {
annotationProcessor project(':ViewModelAnnotationProcessor')
implementation project(':ViewModelAnnotation')
}

完整 Sample 见 https://github.com/yhaolpz/AptSample.