Gradle中插件可以分為兩類:腳本插件和對象插件。
腳本插件
腳本插件就是一個普通的gradle建構腳本,通過在一個foo.gradle腳本中定義一系列的task,另一個建構腳本bar.gradle通過 apply from:'foo.gradle'
即可引用這個腳本插件。
首先在項目根目錄下建立一個config.gradle檔案,在該檔案中定義所需的task。

//config.gradle
project.task("showConfig") {
doLast {
println("$project.name:showConfig")
}
}
然後在需要引用的module的建構腳本中引用
config.gradle
,例如在
app.gradle
中,由于
config.gradle
建立在根目錄下,與app這個子產品平級,是以需要注意路徑問題
../config.gradle
//app.gradle
apply from: '../config.gradle'
就是這麼簡單,此時運作gradle建構即可執行showConfig這個task,
garretdeMacBook-Pro:CustomPlugin garretwei$ ./gradlew showConfig
> Task :app:showConfig
app:showConfig
對象插件
對象插件是指實作了org.gradle.api.Plugin接口的類。Plugin接口需要實作 void apply(T target)
這個方法。該方法中的泛型指的是此Plugin可以應用到的對象,而我們通常是将其應用到Project對象上。
編寫對象插件主要有三種方式:
- 直接在gradle腳本檔案中
- 在buildSrc目錄下
- 在獨立的項目下
在gradle腳本檔案中
直接在gradle腳本中編寫這個方式是最為簡單的。打開
app.gradle
檔案,在其中編寫一個類實作Plugin接口。
//app.gradle
class CustomPluginInBuildGradle implements Plugin<Project> {
@Override
void apply(Project target) {
target.task('showCustomPluginInBuildGradle'){
doLast {
println("task in CustomPluginInBuildGradle")
}
}
}
}
然後通過插件類名引用它
//app.gradle
apply plugin: CustomPluginInBuildGradle
執行插件中定義的task
garretdeMacBook-Pro:CustomPlugin garretwei$ ./gradlew -q showCustomPluginInBuildGradle
task in CustomPluginInBuildGradle
除了直接寫在某個子產品的建構腳本中,我們還可以将插件寫在工程根目錄下的buildSrc目錄下,這樣可以在多個子產品之間複用該插件。
雖然buildSrc是Gradle在項目中配置自定義插件的預設目錄,但它并不是标準的Android工程目錄,是以使用這種方式需要我們事先手動建立一個buildSrc目錄。目錄結構如下:
buildSrc目錄結構
在buildSrc/src/main/groovy目錄下建立自定義plugin,并在build.gradle中引用groovy插件
// buildSrc/build.gradle
apply plugin: 'groovy'
dependencies {
compile gradleApi()
compile localGroovy()
}
然後編寫plugin代碼
class CustomPluginInBuildSrc implements Plugin<Project> {
@Override
void apply(Project project) {
project.task('showCustomPluginInBuildSrc') {
doLast {
println('task in CustomPluginInBuildSrc')
}
}
}
}
由于buildSrc目錄是gradle預設的目錄之一,該目錄下的代碼會在建構是自動編譯打包,并被添加到buildScript中的classpath下,是以不需要任何額外的配置,就可以直接被其他子產品的建構腳本所引用。
注意這裡引用的方式可以是通過類名引用,也可以通過給插件映射一個id,然後通過id引用。
通過類名引用插件的需要使用全限定名,也就是需要帶上包名,或者可以先導入這個插件類,如下
apply plugin: com.gary.plugin.CustomPluginInBuildSrc
或者
import com.gary.plugin.CustomPluginInBuildSrc
apply plugin: CustomPluginInBuildSrc
通過簡單的id的方式,我們可以隐藏類名等細節,使的引用更加容易。映射方式很簡單,在buildSrc目錄下建立resources/META-INF/gradle-plugins/xxx.properties,這裡的xxx也就是所映射的id,這裡我們假設取名myplugin。具體結構可參考上文buildSrc目錄結構。
myplugin.properties檔案中配置該id所對應的plugin實作類
implementation-class=com.gary.plugin.CustomPluginInBuildSrc
此時就可以通過id來引用對于的插件了
//app.gradle
apply plugin: 'myplugin'
在獨立工程下
在buildSrc下建立的plugin隻能在該工程下的多個子產品之間複用代碼。如果想要在多個項目之間複用這個插件,我們就需要在一個單獨的工程中編寫插件,将編譯後的jar包上傳maven倉庫。
這裡為了不增加複雜度,我們還是在該工程下建立一個standaloneplugin子產品。隻需要明白我們完全可以在一個獨立的工程下來編寫插件。
standAlonePlugin目錄結構
從目錄結構來看,和buildSrc目錄是一緻的。差別在于buildSrc下的代碼在建構時會自動編譯并被引用。而我們在獨立項目中編寫的插件如果要能正确的被引用到,需要上傳到maven倉庫中,然後顯式地在需要引用的項目中的buildSrcipt中添加對該構件的依賴。
插件代碼
class StandAlonePlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.task('showStandAlonePlugin') {
doLast {
println('task in StandAlonePlugin')
}
}
}
}
插件項目建構腳本
apply plugin: 'groovy'
apply plugin: 'maven'
dependencies {
compile gradleApi()
compile localGroovy()
}
group = 'com.gary.plugin'
version = '1.0.0'
uploadArchives {
repositories {
mavenDeployer {
repository(url: uri('../repo'))
}
}
}
這裡與buildSrc不同的是,我們引用了
apply plugin 'maven'
,通過maven插件,我們可以輕松的配置group,version 以及 uploadArchives的相關屬性,然後執行
./gradlew uploadArchives
這個任務,就可以将構件打包後上傳到maven倉庫了。同樣為了示例簡單,我們上傳到一個本地倉庫
repository(url: uri('../repo'))
中。
上傳之後就可以在項目根目錄下找到
repo
這個目錄了。最後我們通過給根目錄下的build.gradle配置buildScript的classpath,就可以引用這個插件了。注意,classpath的格式為
group:artifact:version
buildscript {
repositories {
maven {
url uri('repo')
}
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.gary.plugin:standaloneplugin:1.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
引用插件
//app.gradle
apply plugin: 'standAlonePlugin'
執行StandAlonePlugin中定義的任務
./gradlew -q showStandAlonePlugin
task in StandAlonePlugin
總結
- 插件分為腳本插件和對象插件。
- 腳本插件通過
引用。apply from: 'foo.gradle'
- 對象插件可以在目前建構腳本下直接編寫,也可以在buildSrc目錄下編寫,還可以在完全獨立的項目中編寫,通過插件類名或是id引用。
apply plugin: ClassName
apply plugin:'pluginid'
本文所編寫的插件代碼隻是起到簡單說明,主要介紹插件編寫方式。實際插件編寫過程中需要用到的Extension,以及Project和Gradle相關的生命周期方法等api并未涉及。相關知識點可以參考本系列文章中的【實戰,從0到1完成一款Gradle插件】。
最後
更多Android進階技術,面試資料系統整理分享,職業生涯規劃,産品,思維,行業觀察,談天說地。可以加Android架構師群;701740775。