Android开发 组件化中APT的使用

什么是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生成互通的类

猜你喜欢

转载自blog.csdn.net/yanwenyuan0304/article/details/106020717