Android 高级技术 APT 入门

什么是APT?

APT(Annotation Processing Tool)注解处理工具,它是jdk提供的一套工具,通过这套工具我们可以在编译时,根据注解自动生成Java代码,如果你用过dagger,bindview,GreenDao等开源库那么相信你对这套东西会有一定了解。

APT的适用场景

通过少量的注解生成大量重复的代码,从而减少工作量,而且可以避免犯错。

APT入门

接下来我们先写一个小demo:通过在编译时同过自定义注解@Test自动生成一个类APTTest,该类提供一个getString()方法,返回一个字符串Hello APT

  1. 新建两个Java Library,注意必须是Java Library,Android Library不提供需要的支持类

    新建Java Library

    项目结构

    其中lib_annotation用来提供注解,lib_compiler用来生成代码

  2. 在lib_annotation下,编写注解:

    package com.sunchenhao.lib_annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @description:
     * @author:孙晨昊
     * @date: 2020/1/5
     **/
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Test {
    }
    
  3. 给app和lib_compiler添加依赖(基于gradle:3.5.3,老版本可能会有不同):

      //app
      dependencies {
          implementation project(path: ':lib_annotation')
          annotationProcessor project(path: ':lib_compiler')
      }
    
      //:lib_compiler
      dependencies {
          compileOnly 'com.google.auto.service:auto-service:1.0-rc6'
          implementation 'com.squareup:javapoet:1.11.1'
          annotationProcessor 'com.google.auto.service:auto-service:1.0-rc6'
          implementation project(path: ':lib_annotation')
      }
    
  4. 在lib_compiler下编写processer

    package com.sunchenhao.lib_compiler;
    
    import com.google.auto.service.AutoService;
    import com.squareup.javapoet.JavaFile;
    import com.squareup.javapoet.MethodSpec;
    import com.squareup.javapoet.TypeSpec;
    
    import java.io.IOException;
    import java.util.Set;
    
    import javax.annotation.processing.AbstractProcessor;
    import javax.annotation.processing.Processor;
    import javax.annotation.processing.RoundEnvironment;
    import javax.annotation.processing.SupportedAnnotationTypes;
    import javax.annotation.processing.SupportedSourceVersion;
    import javax.lang.model.SourceVersion;
    import javax.lang.model.element.Modifier;
    import javax.lang.model.element.TypeElement;
    
    /**
     * @description:
     * @author:孙晨昊
     * @date: 2020/1/5
     **/
    @AutoService(Processor.class) //表明这个类是一个processor
    @SupportedAnnotationTypes({"com.sunchenhao.lib_annotation.Test"})//声明需要匹配的注解
    @SupportedSourceVersion(SourceVersion.RELEASE_8)//支持的Java版本
    public class TestProcessor extends AbstractProcessor {
    
        @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
            //新建一个方法
            MethodSpec getString = MethodSpec.methodBuilder("getString")
                    .addModifiers(Modifier.PUBLIC)
                    .returns(String.class)
                    .addCode("return \"Hello APT\";\n")
                    .build();
            //新建一个类
            TypeSpec testType = TypeSpec.classBuilder("APTTest").addModifiers(Modifier.PUBLIC).addMethod(getString).build();
    
            //生成这个类
            JavaFile javaFile = JavaFile.builder("com.sunchenhao.myapt", testType)
                    .build();
            try {
                javaFile.writeTo(processingEnv.getFiler());
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println(e);
            }
            return true;
        }
    }
    
  5. 在app下新建接口ITest声明注解为@Test:

    package com.sunchenhao.myapt;
    
    import com.sunchenhao.lib_annotation.Test;
    
    /**
     * @description:
     * @author: 孙晨昊
     * @date: 2020/1/5
     **/
    @Test
    public interface ITest {
    }
    
  6. 按下Ctrl+F9,编译完成后在app->build->generated->ap_generated_sources目录下就可以找到我们生成的类。接下来我们就可以在我们的项目中使用这个类。

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <TextView
            android:id="@+id/test"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
    package com.sunchenhao.myapt;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ((TextView)findViewById(R.id.test)).setText(new APTTest().getString());
        }
    }    
    
  7. 运行代码

    运行效果

Demo

github:https://github.com/Charles199310/MyApt

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 2,694评论 0 3
  • 什么是注解(Annotation):Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和...
    九尾喵的薛定谔阅读 3,155评论 0 2
  • 先建三个module,分别为Butterknife ButterKnife-Annotions ButterKni...
    噜噜丶阅读 493评论 0 1
  • Java 8自Java 5(发行于2004)以来最具革命性的版本。Java 8 为Java语言、编译器、类库、开发...
    huoyl0410阅读 625评论 1 2
  • Java 8自Java 5(发行于2004)以来最具革命性的版本。Java 8 为Java语言、编译器、类库、开发...
    谁在烽烟彼岸阅读 888评论 0 4