O uso do APT na componentização do desenvolvimento Android

O que é APT?

APT (Ferramenta de processamento de anotações)

É uma ferramenta de processamento de anotações. Detecta as anotações nos arquivos de código-fonte e produz automaticamente o código com base nas anotações. Se quiser que um processador de anotações personalizado funcione normalmente, deve processá-lo por meio da ferramenta APT. Também pode ser entendido que somente após a ferramenta APT ser declarada, o interpretador de anotação personalizado pode ser executado durante a compilação do programa.

Entendimento popular: de acordo com as regras, ajude-nos a gerar código e gerar arquivos de classe

Android Studio 3.4.1 + Gradle5.1.1 (versão recomendada)

Como usar o APT na componentização?

O desenvolvimento de componentes é para desacoplamento e alto isolamento. Cada módulo é independente. Se quisermos obter uma interação direta entre cada componente, podemos usar os seguintes métodos:

  • A tecnologia de reflexão e reflexão pode ser bem-sucedida, o custo de manutenção é alto e a restrição @hide da versão alta tende a aparecer
  • EvenTBus EventBean é muitos (um-para-um), um-para-muitos será confuso e difícil de manter (eu não tentei isso)
  • O custo da manutenção implícita da intenção é bom, mas é mais problemático e requer muitas ações no Manifesto para ser mantido
  • BroadCastReceiver requer registro dinâmico (após 7.0), e a parte necessitada envia uma transmissão
  • O carregamento da classe requer um caminho preciso para o nome completo da classe, a manutenção da versão original é relativamente alta e está sujeita a erro humano

Então eu digo muito principalmente para dizer que APT é uma das melhores soluções para realizar a interação no desenvolvimento componentizado.

Então, como usar?

Primeiro, faça o salto de interface entre vários componentes como exemplo:

A interface salta entre o módulo da página principal (MainActivity) e o módulo de pedido (OrderActivity):

Um, crie uma nova classe de anotação

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)//RetentionPolicy.CLASS 编译期预编译的操作
public @interface ARouter {

    //详细路由器路径(必填),如:"/app/MainActivity"
    String path();

    // 从path中截取出来
    String group() default "";
}

2. Crie um novo ARouterProcessor para herdar AbstractProcessor para implementar o trabalho de anotação

ARouterProcessor herda AbstractProcessor, para a classe com a anotação ARouter, uma nova classe é gerada para uso interativo durante a compilação


@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;
    }
}

3. Adicione esta anotação às classes MainActivity e OrderActivity e use a classe gerada para pular para o
código 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));
    }
}

Código 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));
    }
}

Resumo: O desenvolvimento de componentes é usar o APT dinamicamente para gerar classes interoperáveis

Acho que você gosta

Origin blog.csdn.net/yanwenyuan0304/article/details/106020717
Recomendado
Clasificación