Gradle 中的依賴
Gradle 中的依賴可以分爲腳本文件依賴、插件依賴以及包依賴。
腳本文件依賴
隨着項目結構的複雜,一個 build.gradle 已經無法滿足我們的需求了,尤其是對依賴庫版本的配置,如果多個 project 都需要用到某個依賴庫,稍有不慎版本就會錯亂,從而引發一些問題。
此時我們期望可以把所有用到的依賴庫版本都配置在同一個文件中,build.gradle 使用這個文件中的版本來依賴相應的版本,Gradle 提供了 apply 方法來依賴其他文件。
apply from: 'config.gradle'
我們可以在 build.gradle 文件中添加上述代碼來依賴 config.gradle 文件,這樣就可以把這個文件中的設置應用到對應的 Project 中去,包括其中的 Task。
插件依賴
插件依賴是指依賴編譯插件,最常見的是我們新建一個 Android 項目時,對應 module 的 build.gradle 文件第一行自動添加的安卓插件:
apply plugin: 'com.android.application'
與上一節的腳本文件依賴一樣,都使用 apply 函數添加依賴,其中 plugin 後面跟的是插件的 ID 或者全限定類名,我們後面會介紹如何設置插件名。
通過上面的一行代碼就可以把這個插件應用到當前的編譯腳本中去,但對於自定義插件來說,我們還需要做一些其他的工作。
對於 Gradle 來說,依賴一個插件需要分如下三步:
1. 設置這個插件對應的倉庫地址
我們首先應該設置一些倉庫地址,告訴 Gradle 應該去哪裏下載我們配置的這些插件和依賴包。
設置倉庫地址通過 repositories 函數來實現,當我們創建好一個項目後,在根 build.gradle 文件中一般會自動添加如下兩個依賴倉庫:
allprojects {
repositories {
google()
jcenter()
}
}
上面代碼就是在本項目中添加了兩個倉庫:google 以及 jcenter.
因爲 google 和 jcenter 兩個倉庫比較常用,所以默認提供了這兩個方法,如果我們希望設置自己的倉庫也是可以的,以 Github 的倉庫爲例:
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
實際上,除了通過上述的方式配置倉庫地址外,還有另一種方式設置倉庫,就是在項目中創建 buildSrc 子項目,這個後面會詳細介紹。
2. 設置這個插件所在包的全限定名
倉庫地址配置好後,我們就可以使用該倉庫中的插件了,插件依賴使用 classpath 函數來完成:
buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
}
}
這一步相當於去上面配置的倉庫中下載這個插件所在的依賴包,這個依賴包中可能包含很多個插件,有了依賴包我們纔是使用其中的插件。
3. 通過插件名將該插件設置到對應的編譯腳本中
到了這裏,準備工作就已經全部搞定了,該有的東西都有了,現在如果我們希望在當前的編譯腳本中使用某個插件,直接使用上面介紹過的 apply 函數既可:
apply plugin: 'com.android.application'
另外,這裏面說的插件是指編譯腳本插件,是在編譯時使用的工具,用來控制編譯的,跟實際的項目開發時的代碼沒有關係,與我們常說的在項目開發中使用的依賴包不同。
包依賴
包依賴其實是個籠統的概念,包括上面說的插件依賴其實也屬於包依賴,本章所說的包依賴單純是指在實際項目開發中使用的一些第三方的依賴庫,例如 OkHttp、Gson 等等,這其實不屬於編譯腳本的範疇,但畢竟也是 Gradle 依賴的一部分,所以也大概說一下。
包依賴與腳本依賴本質上都一樣,都分爲三步:
1. 設置包所在的倉庫
設置倉庫地址跟上面說的一樣,都是通過 repositories 函數來實現。
2. 下載需要使用的依賴包
聲明依賴包需要在對應項目的 build.gradle 的 dependencies 函數中完成。
dependencies {
// 聲明一個本地模塊的依賴
implementation project(":mylibrary")
// 聲明一個本地二進制包的依賴
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 聲明一個遠程二進制包的依賴
implementation 'com.example.android:app-magic:12.3'
}
此外,還有很多種不同的聲明的依賴方式,每種方式都具有不同的依賴特質,具體可以看下錶:
表出處:https://developer.android.com/studio/build/dependencies?hl=zh-cn
3. 使用該依賴包
通過上面兩個步驟之後,我們就可以在 Java 代碼或者其他語言的代碼中使用依賴包中的代碼了。
上面就是依賴包的使用方式。我們可以使用 dependencies Task 查看指定項目的依賴樹:
//查看 app 模塊的依賴樹
gradlew app:dependencies
上面的命令將會輸出一個樹形的依賴關係表。
Gradle 插件
上面敘述的 Task 都是完成一些簡單的動能,但對於一些更加複雜,或者可以被更廣泛使用的功能來說,直接在 gradle 文件中定義 Task 已經很難滿足我們的需求了,因此,Gradle 提供了插件的概念來解決這個問題。
編寫 Gradle 插件有兩種方式,一種是創建一個名爲 buildSrc 的子項目,在這個子項目中編寫插件代碼,buildSrc 是 Gradle 插件的默認目錄,會把這個目錄下的插件自動添加到當前項目中去,我們可以在別的子項目中直接使用。
另一種方式是把插件寫在其他目錄,然後上傳到 maven 倉庫,其他項目通過 maven 的方式依賴這個插件。
爲了方便起見,這裏以 buildSrc 爲例,由於 buildSrc 不是標準的 Android 項目,所以我們先手動 New module 一個子模塊出來,然後選擇 Java Library。
創建好後,打開這個模塊的 build.gradle 文件,把最上面一行的 java-library 插件改成 groovy 插件,以及添加需要的依賴包:
//apply plugin: 'java-library'
apply plugin: 'groovy'
dependencies {
implementation gradleApi()
implementation localGroovy()
}
然後,因爲插件使用的是 groovy 編寫,所以還需要把 buildSrc 下面的 java 目錄刪掉改成 groovy 目錄,完成後如下圖所示:
這樣一個 groovy 項目就創建好了。
我們現在開始編寫插件,編寫插件的方式很簡單,只需要在 groovy 目錄下創建一個實現了 Plugin 接口的 groovy 類既可:
class PrintVersionPlugin implements Plugin<Project> {
@Override
void apply(Project target) {
target.tasks.create("PrintVersionTask"){
doLast{ println("PrintVersionPlugin version:1.0") }
}
}
}
Plugin 接口只包含一個 apply 方法,我們拿到該方法的 project 參數後,就可以做一些自己的操作了,project 提供了豐富的 api,我們可以完成很多事情,例如創建一個 Task。
插件寫好後,我們還需要爲該插件創建一個 id,使用這個插件時直接使用這個 id 既可。創建 ID 映射很簡單,在 groovy 同級目錄下創建一個 resources\META-INF\gradle-plugins 文件夾,然後在這個文件下創建 ID 映射文件,文件名就是這個插件的 id,後綴爲 properties,然後把插件類的全限定名按照如下格式寫進去既可。
例如我們把上面插件的 ID 命名爲 printVersion,那麼我們創建一個 printVersion.properties 文件,然後編寫如下代碼:
implementation-class=com.zhangke.gradle.PrintVersionPlugin
此時的 buildSrc 項目目錄結構如下:
這個時候我們就可以在別的子項目中使用這個插件了:
apply plugin: 'printVersion'
如果我們希望在一個單獨的目錄下編寫插件,然後上傳到 maven 倉庫也是可以的,上傳 maven 倉庫可以用 maven 插件很容易實現,這裏就不具體敘述了。