1. 程式人生 > >你必須知道的APT、annotationProcessor、android-apt、Provided、自定義註解

你必須知道的APT、annotationProcessor、android-apt、Provided、自定義註解

你可能經常在build.gradle檔案中看到,這樣的字眼,annotationProcessor、android-apt、Provided,它們到底有什麼作用?下面就一起來看看吧

1、什麼是APT?

隨著一些如ButterKnife,dagger等的開源註解框架的流行,APT的概念也越來越被熟知。

annotationProcessor和android-apt的功能是一樣的,它們是替代關係,在認識它們之前,先來看看APT。

APT(Annotation Processing Tool)是一種處理註釋的工具,它對原始碼檔案進行檢測找出其中的Annotation,根據註解自動生成程式碼。 Annotation處理器在處理Annotation時可以根據原始檔中的Annotation生成額外的原始檔和其它的檔案(檔案具體內容由Annotation處理器的編寫者決定),APT還會編譯生成的原始檔和原來的原始檔,將它們一起生成class檔案。

APT的處理要素

  註解處理器(AbstractProcess)+程式碼處理(javaPoet)+處理器註冊(AutoService)+apt
  

使用APT來處理annotation的流程

  1. 定義註解(如@automain)
  2. 定義註解處理器,自定義需要生成程式碼
  3.使用處理器
  4.APT自動完成如下工作。

這裡寫圖片描述

2、annotationProcessor

annotationProcessor是APT工具中的一種,他是google開發的內建框架,不需要引入,可以直接在build.gradle檔案中使用,如下

dependencies {
     annotationProcessor project(':xx'
) annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0' }

3、android-apt

android-apt是由一位開發者自己開發的apt框架,原始碼託管在這裡,隨著Android Gradle 外掛 2.2 版本的釋出,Android Gradle 外掛提供了名為 annotationProcessor 的功能來完全代替 android-apt ,自此android-apt 作者在官網發表宣告最新的Android Gradle外掛現在已經支援annotationProcessor,並警告和或阻止android-apt ,並推薦大家使用 Android 官方外掛annotationProcessor。

但是很多專案目前還是使用android-apt,如果想替換為annotationProcessor,那就要知道android-apt是如何使用的。下面就來介紹一下

3.1、新增android-apt到Project下的build.gradle中

//配置在Project下的build.gradle中
buildscript {
    repositories {
      mavenCentral()
    }
    dependencies {
        //替換成最新的 gradle版本
        classpath 'com.android.tools.build:gradle:1.3.0'
        //替換成最新android-apt版本
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }
}

3.2、在Module中build.gradle的配置

通常在使用的時候,使用apt宣告註解用到的庫檔案。專案依賴可能分為多個部分。例如Dagger有兩個元件Dagger-compiler和dagger。dagger-commpiler僅用於編譯時,執行時必需使用dagger。


//配置到Module下的build.gradle中
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'

dependencies {
 apt 'com.squareup.dagger:dagger-compiler:1.1.0'
 compile 'com.squareup.dagger:dagger:1.1.0'
}

基本使用就是上面這兩點,想用annotationProcessor替代android-apt。刪除和替換相應部分即可

4、Provided 和annotationProcessor區別

annotationProcessor

只在編譯的時候執行依賴的庫,但是庫最終不打包到apk中,

編譯庫中的程式碼沒有直接使用的意義,也沒有提供開放的api呼叫,最終的目的是得到編譯庫中生成的檔案,供我們呼叫。

Provided

Provided 雖然也是編譯時執行,最終不會打包到apk中,但是跟apt/annotationProcessor有著根本的不同。

A 、B、C都是Library。 
A依賴了C,B也依賴了C 
App需要同時使用A和B 
那麼其中A(或者B)可以修改與C的依賴關係為Provided

A這個Library實際上還是要用到C的,只不過它知道B那裡也有一個C,自己再帶一個就顯得多餘了,等app開始執行的時候,A就可以通過B得到C,也就是兩人公用這個C。所以自己就在和B匯合之前,假設自己有C。如果執行的時候沒有C,肯定就要崩潰了。

總結一下,Provided是間接的得到了依賴的Library,執行的時候必須要保證這個Library的存在,否則就會崩潰,起到了避免依賴重複資源的作用。

5、自定義註解

6、使用APT的簡單專案——自定義註解

6.1、新增一個java Library Module 名為apt-lib, 編寫註解類:

@Target(ElementType.TYPE)  //作用在類上
@Retention(RetentionPolicy.RUNTIME)//存活時間
public @interface AutoCreate {

}

6.2、新增一個java Library Module 名為apt-process,編寫類來處理註解。以後使用上面的@AutoCreate,就會根據下面這個類生成指定的java檔案

@AutoService(Processor.class)
public class TestProcess extends AbstractProcessor {
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return Collections.singleton(AutoCreat.class.getCanonicalName());
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {

        MethodSpec main = MethodSpec.methodBuilder("main")
                .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
                .returns(void.class)
                .addParameter(String[].class, "args")
                .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
                .build();

        TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
                .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
                .addMethod(main)
                .build();

        JavaFile javaFile = JavaFile.builder("com.songwenju.aptproject", helloWorld)
                .build();

        try {
            javaFile.writeTo(processingEnv.getFiler());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
}

6.2.1、需要使用的lib

dependencies {
    compile project(':apt-lib')
    compile 'com.squareup:javapoet:1.8.0'
    compile 'com.google.auto.service:auto-service:1.0-rc2'
}

至此一個簡單的自定義註解類,就完成了,只是生成了一個HelloWorld.java檔案,裡面只有一個main()函式

6.3、自定義註解類的使用

使用的話,更簡單。在java檔案中使用如下:

@AutoCreat
public class MainActivity extends AppCompatActivity {

    @Override

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

配置build.gradle檔案

dependencies {
    //新增下面這句就可以了
    compile project(":apt-lib")
    annotationProcessor project(':apt-process')
}

參考:

關注我的公眾號,輕鬆瞭解和學習更多技術
這裡寫圖片描述