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'}
  • 1
  • 2
  • 3
  • 4

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'    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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'}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

基本使用就是上面這兩點,想用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
  • 1
  • 2
  • 3
  • 4

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 {}
  • 1
  • 2
  • 3
  • 4
  • 5

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;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

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'}
  • 1
  • 2
  • 3
  • 4
  • 5

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

6.3、自定義註解類的使用

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

@AutoCreatpublic class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

配置build.gradle檔案

dependencies {    //新增下面這句就可以了    compile project(":apt-lib")    annotationProcessor project(':apt-process')}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

參考:

 

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