APT,就是Annotation Processing Tool 的简称,就是可以在代码编译期间对注解进行处理,并且生成Java文件,减少手动的代码输入。一些大名鼎鼎的框架如 Retrofit, Arouter 都运用了 APT 技术。
在本片文章中我们将利用 APT 技术实现类似 ARouter 的路由功能.
不多说,先附上本文中的代码地址:APTdemo
github.com/square/java…
实现效果
常用的 Activity 跳转方式:
startActivity(new Intent(MainActivity.this, TwoActivity.class));
复制代码
我们希望通过以下方式达到 Activity 跳转的目的:
SRouter.getInstance().navigate(MainActivity.this, "router_two");
复制代码
注解
创建annotation
library, 首先我们在 library 中定义注解,通过它我们可以找到哪些 Activity 需要添加到路由中
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface Router {
String name();
}
复制代码
注解处理器 - compile
创建compile
library,依赖 annotation
模块, 注意创建的时候选择 java-libray, 创建RouterProcessor
类继承自 AbstractProcessor。我们需要实现 4 个方法,前3个方法简单的写法很固定,简单讲一下他们的作用吧;
- init()方法可以初始化拿到一些使用的工具,比如文件相关的辅助类 Filer;元素相关的辅助类Elements;日志相关的辅助类Messager;
- getSupportedSourceVersion()方法返回 Java 版本;
- getSupportedAnnotationTypes()方法返回要处理的注解;
其中最核心的是 process()
方法,通过javapoet 再结合注解我们就可以成相应的类。 最终我们希望生成的类是这样的:
public final class Router$$GroupApp implements IRouterGroup {
private Map routeMap = new HashMap();
public Router$$GroupApp() {
this.routeMap.put("router_two", "com.slyser.aptdemo.TwoActivity");
}
public String getActivityName(String routeName) {
return null != this.routeMap && !this.routeMap.isEmpty() ? (String)this.routeMap.get(routeName) : "";
}
}
复制代码
实现代码并不复杂,就是写起来很繁琐,还好 javapoet 为我们省了不少事。
注册注解处理器
编译的时候 JVM
怎么找到我们自定义的注解处理器?这个时候就要用到 SPI
机制。简单的用法就是在 compile
模块下新建 resources/META-INF/services 文件,创建这个文件很容易出错,大家可以使用 google 出品的 auto-service
,通过注解就可以很方便的问我们创建相应的文件
添加
auto-service
的 gradle 依赖:implementation 'com.google.auto.service:auto-service:1.0-rc3'
核心库 - api
创建 api
library, 该库很简单,就只有 SRouter
一个类,核心就是反射创建注解处理器生成的对象,拿到 Activity 的 Class,完成 activity 的跳转.
使用
在 Activity 上添加注解
@Router(name = "router_two")
public class TwoActivity extends AppCompatActivity
复制代码
跳转
SRouter.getInstance().navigate(this, "router_two");
复制代码
这样一个简单的路由跳转就完成了
总结
APT
技术其实就是自定义注解和注解处理器,在编译期间生成Java文件,类似于IOC控制反转,可以方便的进行解耦,在多模块开发时可以基于APT技术构造一套路由框架,去除startActivity等造成的类依赖。