什么是APT?
APT(Annotation Processing Tool)
是一种处理注释的工具,它对源代码文件检测找出其中的Annotation,根据注解自动生产代码,如果想要自定义的注解处理器能够正常运行,必须要通过APT工具来进行处理。也可以这样理解,只有通过声明APT工具后,程序在编译期间自定义注解解释器才能执行。
通俗理解:根据规则,帮我们生成代码,生成类文件
Android Studio 3.4.1 + Gradle5.1.1(推荐版本)
组件化中怎么使用APT?
组件化开发是为了解耦,高度的隔离,各个模块都是独立的,我们要想实现各个组件直接的交互,可以使用如下方式:
- 反射 反射技术可以成功,维护成本较高且容易出现高版本@hide限制
- EvenTBus EventBean非常多(一对一),一对多就会混乱不堪,难以维护(这个我没尝试过)
- 隐式意图 维护成本还好,只是比较麻烦,需要维护太多Manifest中的action
- BroadCastReceiver 需要动态注册(7.0后),需要方发送广播
- 类加载 需要准确的的全类名路径,维护正版较高且容易出现人为失误
然后说这么多主要是说APT 是最好的组件化开发中实现交互的很好的方案之一。
那么怎么使用呢?
首先以各个组件之间的界面跳转为例子:
首页模块(MainActivity) 与 订单模块(OrderActivity)之间的界面跳转:
一、新建一个注解类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)//RetentionPolicy.CLASS 编译期预编译的操作
public @interface ARouter {
//详细路由器路径(必填),如:"/app/MainActivity"
String path();
// 从path中截取出来
String group() default "";
}
二、新建ARouterProcessor继承AbstractProcessor来具体实现注解的工作
ARouterProcessor继承AbstractProcessor,给添加了ARouter注解的类,在编译期新生成一个类用于交互使用
@AutoService(Processor.class)
@SupportedAnnotationTypes("com.goodboy.annotation.ARouter")
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedOptions("content")
public class ARouterProcessor extends AbstractProcessor {
//操作Element工具类
private Elements elementUtils;
//type(类信息)工具类
private Types typeUtils;
//用来输出警告,错误等日志
private Messager messager;
//文件生成器
private Filer filer;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
elementUtils = processingEnvironment.getElementUtils();
typeUtils = processingEnvironment.getTypeUtils();
messager = processingEnvironment.getMessager();
filer = processingEnvironment.getFiler();
String content = processingEnvironment.getOptions().get("content");
messager.printMessage(Diagnostic.Kind.NOTE,content);
}
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
if (set.isEmpty())return false;
//获取项目中所有使用使用了ARouter注解的节点
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(ARouter.class);
//遍历所有的类节点
for (Element element : elements) {
//类节点之上,就是包节点
String packageName = elementUtils.getPackageOf(element).getQualifiedName().toString();
//获取简单类名
String className = element.getSimpleName().toString();
messager.printMessage(Diagnostic.Kind.NOTE,"被注解的类有:" + className);
// 最终我们想要生成的类文件 如:MainActivity$$ARouter
String finalClassName = className + "$$ARouter";
// 公开课写法,也是EventBus写法(https://github.com/greenrobot/EventBus)
try {
// 创建一个新的源文件(Class),并返回一个对象以允许写入它
JavaFileObject sourceFile = filer.createSourceFile(packageName + "." + finalClassName);
// 定义Writer对象,开启写入
Writer writer = sourceFile.openWriter();
// 设置包名
writer.write("package " + packageName + ";\n");
writer.write("public class " + finalClassName + " {\n");
writer.write("public static Class<?> findTargetClass(String path) {\n");
// 获取类之上@ARouter注解的path值
ARouter aRouter = element.getAnnotation(ARouter.class);
writer.write("if (path.equals(\"" + aRouter.path() + "\")) {\n");
writer.write("return " + className + ".class;\n}\n");
writer.write("return null;\n");
writer.write("}\n}");
// 最后结束别忘了
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
}
三、给MainActivity 、OrderActivity类加上该注解,并使用生成的类来跳转
MainActivity代码
@ARouter(path = "/app/MainActivity")
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void jump(View view){
Class<?> targetClass = OrderActivity$$ARouter.findTargetClass("/app/OrderActivity");
startActivity(new Intent(this, targetClass));
}
}
OrderActivity代码
@ARouter(path = "/app/OrderActivity")
public class OrderActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order);
Log.d("mile", "--->OrderActivity");
}
public void jump(View view) {
Class<?> targetClass = MainActivity$$ARouter.findTargetClass("/app/MainActivity");
startActivity(new Intent(this, targetClass));
}
}
总结:组件化开发,就是动态的使用APT生成互通的类