編譯時(shí)生成代碼

ButterKnife使我們經(jīng)常使用的一款View注入框架,使用方便,特點(diǎn)是ButterKnife使用的是編譯時(shí)生成代碼,而不是反射注入。那么我就有一個(gè)問(wèn)題,ButterKnife究竟是如何在編譯時(shí)生成代碼的呢?這就是這篇文章的目的了。。。

先做一個(gè)例子我們來(lái)試著在編譯時(shí)做一些操作。
介紹幾個(gè)概念

1.APT

APT-annotation processing tool是在編譯時(shí),掃描和處理注解的一個(gè)構(gòu)建工具,該工能由 javac 來(lái)實(shí)現(xiàn),我們可以在 javac 編譯時(shí)源代碼額外生成 java 源代碼(也可以是其它類(lèi)型的文件)。關(guān)于如何處理注解我們需要了解AbstractProcessor這個(gè)類(lèi)。Annotation Processor的實(shí)現(xiàn),都需要繼承自該類(lèi)。

2.AbstractProcessor

AbstractProcessor 是 javac 掃描和處理注解的關(guān)鍵類(lèi)。介紹兩個(gè)關(guān)鍵的方法,

(1)public Set<String> getSupportedAnnotationTypes()

制定需要處理哪些注解 ,返回值是注解全類(lèi)名的Set。

(2)public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)

Processor的主方法,可以在該方法中處理注解,并生成Java代碼,并可以通過(guò)RoundEnvironment獲取到被注解的元素。

先創(chuàng)建三個(gè)Module

1.app (Android Module已存在)

2.api (Java Module存放我們的注解)

3.compiler (Java Module 存放我們的Processor)

聲明插件依賴(lài)

聲明插件android-apt,這個(gè)是Android Studio 與annotation processors結(jié)合的一個(gè)插件,在構(gòu)建工程時(shí)將輔助javac執(zhí)行processor, 在根目錄的build.gradle添加:

  classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

api Module

定義注解

    @Retention(RetentionPolicy.CLASS)
    @Target(ElementType.TYPE)
    public @interface MyAnnotation {
    }

app module

在app的build.gradle:

  apply plugin: 'com.neenbedankt.android-apt'

  dependencies {
      ...
      compile project(':api')
      apt project(':compiler')
      ...
  }

使用api中定義的注解

    @MyAnnotation
    public class Bean {
    }

compiler module

在build.gradle:

  apply plugin: 'java'

  dependencies {
      compile fileTree(include: ['*.jar'], dir: 'libs')
      compile 'com.google.auto.service:auto-service:1.0-rc3'
      compile 'com.squareup:javapoet:1.8.0'
      compile project(':api')
  }

這里添加了三個(gè)依賴(lài)

1.api: 我們需要獲取到我們定義的MyAnnotation注解

2.auto-service:用來(lái)自動(dòng)生成 javax.annotation.processing.Processor 文件。location:https://github.com/google/auto/tree/master/service

3.javapoet:自動(dòng)生成代碼的工具類(lèi)庫(kù)。location:https://github.com/square/javapoet

然后創(chuàng)建我們的Processor類(lèi)。

@AutoService(Processor.class)
public class MyProcessor extends AbstractProcessor {

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return Collections.singleton(MyAnnotation.class.getCanonicalName());
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        System.out.println("Message");
        return true;
    }
}

這時(shí)clean下Project 然后運(yùn)行./gradlew assemble就可以看到輸出的Message。

JavaPoet是一個(gè)用來(lái)生成.java源文件的Java API。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容