热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AndroidStudio中使用apt

AndroidStudio中使用apt一、前言你还在对着枯燥的重复代码一味复制粘贴吗?这样跟搬砖有何区别?你是否曾想过:你用代码编写出一个自动化的APP,但为何代码本身却缺少了活力

Android Studio中使用apt

一、前言

你还在对着枯燥的重复代码一味复制粘贴吗?这样跟搬砖有何区别?你是否曾想过:你用代码编写出一个自动化的APP,但为何代码本身却缺少了活力?掌握android-apt,杜绝重复代码,让你写代码如写诗般优雅。

二、何为apt?

apt意为:annotation processing tool(注解处理工具),这家伙可神奇了,它能通过注解,在编译期自动生成特定的java文件,实现自动编写代码。

问:有什么用?凭我自己本事能写出来的代码,为什么要自动化?
大哥,你这是又想施展你的复制粘贴大法了吗?稍安勿躁,细看完这篇文章,你会爱上这家伙的。

鼎鼎大名的ButterKnife、Dagger2这两个开源库,相信你一定有听过,你应该知道我为什么提到它们了吧。没错!这两个开源库都是基于apt的。

三、说了这么多,要怎么用啊?别急,我们先搭建环境(基于gradle插件2.2.0以上版本)

1.在android studio中新建一个java module,用于存装注解处理逻辑,名字随便啦,反正我一般都取名:apt。很重要的事:在app module中添加注解处理依赖:annotationProcessor project(‘:apt’)
(解释原因:由于android的module中不包含有apt相关类,因此需要新建一个java module来编写apt逻辑。什么?你不信?不信你写个类继承AbstractProcessor试试)

2.再次新建一个module(android、java都可以),用于存装注解,名字也随便,反正我这里取名为:anno,并且在app、apt的build.gradle文件下,添加依赖compile project(‘:anno’)
(为什么要新建module去盛装注解类,而不放到app module或者apt module中去:最主要的原因就是app module与apt module不能直接相互依赖,至于为什么不能直接依赖,我就不细说了,总之一句话:不信你试试看就知道喽!)

3.在apt的build.gradle里,添加如下依赖。到此,我们的环境配置工作就告一段落了。
这里写图片描述
(其中:1.auto-service是用于注解后自动在特定路径下生成配置文件;2.javapoet是用于配合apt便捷生成java文件的工具。相信这样解释大家还云里雾里,不要着急,继续往下看)

四、环境搭建好了,接下来就是秀操作时间

1.首先,在anno module里新建一个注解类

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Test {
    String value();
}

2.在apt module里新建一个注解处理类,继承于AbstractProcessor

public class TestProcessor extends AbstractProcessor{
    @Override
    public boolean process(Set annotations, RoundEnvironment roundEnv) {
        return false;
    }
}

3.既然说apt是要自动生成java文件,那我们就需要拟构出一个目标类。假设我们要生成这样一个类

public class TestClass {

    public static void main(String[] args){
        System.out.println("Hallo world!");
    }

}

4.操作注解处理类,生成目标java文件

@AutoService(Processor.class)
@SupportedAnnotationTypes({
        "com.aop.anno.Test"
})
public class TestProcessor extends AbstractProcessor{

    @Override
    public boolean process(Set annotations, RoundEnvironment roundEnv) {

        //生成TestClass类
        TypeSpec.Builder tb = TypeSpec.classBuilder("TestClass")
                .addModifiers(Modifier.PUBLIC);

        //生成main方法
        MethodSpec.Builder mb = MethodSpec.methodBuilder("main")
                .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
                .returns(void.class)
                .addParameter(String[].class, "args");

        //生成代码块,并添加到main方法中
        for(TypeElement e : ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(Test.class))){
            CodeBlock cb = CodeBlock.builder()
                    .addStatement("$T.out.println(\"$L + $L\")", System.class, 
                    e.getAnnotation(Test.class).value(), e.getSimpleName())
                    .build();
            mb.addCode(cb);
        }

        tb.addMethod(mb.build());

        JavaFile jf = JavaFile.builder("com.example.apt", tb.build()).build();
        //将代码写入java文件中
        try {
            jf.writeTo(processingEnv.getFiler());
        } catch (IOException e) {
            e.printStackTrace();
        }

        return true;
    }
}

大致说下步骤:
(1)添加@AutoService(Processor.class)注解,这个注解会自动在指定路径下生成一个配置文件:
apt/build/classes/main/META-INF/services/javax.annotation.processing.Processor;
(2)添加@SupportedAnnotationTypes注解,配置这个类所要处理的注解类型。(传入String类型参数,格式为:包名+类名);
(3)采用javapoet书写代码构建逻辑,具体用法去这里看看;
(4)生成代码块的主要逻辑是:遍历所有被@Test注解过的类,取出注解内容及类名打印出来。

5.在类上添加@Test注解,这里就用MainActivity来试试

@Test("abc")
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

6.rebuild工程,在app/build/generated/source/apt/debug路径下找到目标java文件。至此,大功告成

这里写图片描述

TestClass代码如下:

public class TestClass {
  public static void main(String[] args) {
    System.out.println("abc + MainActivity");
  }
}

五、然而并没什么暖用?

确实,到此为止,我们确实是用了几十行代码去生成了一个5行代码的TestClass,这种操作来说看起来可以用4个字来形容:闲得蛋疼。
然而,接下来的操作,会让你耳目一新。首先我们新建几个测试类,假如我们新建了这样4个测试类:ActivityA,ActivityB,ActivityC,ActivityD,并且都给他们加上注解@Test。然后rebuild一下,你会发现,我们的TestClass变了样:

public class TestClass {
  public static void main(String[] args) {
    System.out.println("A + ActivityA");
    System.out.println("B + ActivityB");
    System.out.println("C + ActivityC");
    System.out.println("D + ActivityD");
    System.out.println("abc + MainActivity");
  }
}

恍然大悟!原来,是这么玩的!这时候,你是否已经感觉到apt的魅力了呢?是的,它能帮你干掉重复代码,让你杜绝掉复制粘贴。

APT使用案例:APT实用案例一:状态模式之就算违背开闭原则又何妨?


推荐阅读
  • andr ... [详细]
  • 本文介绍了如何使用 Spring Boot DevTools 实现应用程序在开发过程中自动重启。这一特性显著提高了开发效率,特别是在集成开发环境(IDE)中工作时,能够提供快速的反馈循环。默认情况下,DevTools 会监控类路径上的文件变化,并根据需要触发应用重启。 ... [详细]
  • ImmutableX Poised to Pioneer Web3 Gaming Revolution
    ImmutableX is set to spearhead the evolution of Web3 gaming, with its innovative technologies and strategic partnerships driving significant advancements in the industry. ... [详细]
  • 本文介绍了如何在C#中启动一个应用程序,并通过枚举窗口来获取其主窗口句柄。当使用Process类启动程序时,我们通常只能获得进程的句柄,而主窗口句柄可能为0。因此,我们需要使用API函数和回调机制来准确获取主窗口句柄。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本文介绍如何使用阿里云的fastjson库解析包含时间戳、IP地址和参数等信息的JSON格式文本,并进行数据处理和保存。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 本文详细介绍了Java中org.w3c.dom.Text类的splitText()方法,通过多个代码示例展示了其实际应用。该方法用于将文本节点在指定位置拆分为两个节点,并保持在文档树中。 ... [详细]
  • 本文探讨了如何优化和正确配置Kafka Streams应用程序以确保准确的状态存储查询。通过调整配置参数和代码逻辑,可以有效解决数据不一致的问题。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 探讨如何通过编程技术实现100个并发连接,解决线程创建顺序问题,并提供高效的并发测试方案。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 本文将介绍如何使用 Go 语言编写和运行一个简单的“Hello, World!”程序。内容涵盖开发环境配置、代码结构解析及执行步骤。 ... [详细]
author-avatar
抑制不L挑逗烛
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有