一、學(xué)習(xí)目標(biāo)
- 1亥鸠、 了解 Gradle Plugin 的作用是什么妆够?
- 2、 如何去定義一個(gè) Gradle Plugin负蚊?
- 3神妹、 自定義插件擴(kuò)展Extension。
一家妆、Gradle Plugin 的作用是什么鸵荠?
- 模塊化構(gòu)建腳本的功能
- 公共的功能可以抽取出來(lái)成為插件,可以供多個(gè) build.gradle 使用伤极,增加復(fù)用性蛹找。
二、定義一個(gè) Gradle Plugin
2.1哨坪、插件的處理和應(yīng)用
為了將構(gòu)建腳本的邏輯封裝到插件中庸疾,Gradle 需要做以下兩件事:處理插件
,應(yīng)用插件到目標(biāo)中
当编。
- 處理插件
Gradle 會(huì)自動(dòng)找到插件所在的位置届慈,例如一個(gè)
buildSrc
名字 module 就會(huì) Gradle 識(shí)別為插件工程。
- 應(yīng)用插件
一旦插件被應(yīng)用到執(zhí)行的構(gòu)建腳本中,那么插件對(duì)應(yīng)的
apply(T target)
方法就會(huì)被調(diào)用金顿。
2.2臊泌、 Gradle Plugin 創(chuàng)建
將插件定義在 buildSrc 中,這里的 buildSrc 就是當(dāng)前工程下的一個(gè) module 揍拆,Gradle 規(guī)定當(dāng)一個(gè)module被命名為 buildSrc 時(shí)就會(huì)被當(dāng)成插件去處理渠概。
按照以下的步驟來(lái)創(chuàng)建一個(gè)簡(jiǎn)單的插件工程吧:
1、在當(dāng)前工程下創(chuàng)建一個(gè) Java Library 的 module礁凡,起名字為
buildSrc
-
2高氮、將 main/src/java 修改為 main/src/groovy
項(xiàng)目結(jié)構(gòu) 3、創(chuàng)建類(lèi)
PluginTest
實(shí)現(xiàn) Plugin 接口并覆寫(xiě) apply(T garget) 接口
Plugin<T> 是一個(gè)泛型接口顷牌,在定義插件是應(yīng)該將這個(gè)泛型填為 Project 即可剪芍。
class PluginTest implements Plugin<Project> {
@Override
void apply(Project project) {
//定義一個(gè) Task
project.task("MyTask") {
doLast {
println "MyTask doLast invoke..."
}
}
}
}
- 4、在外部應(yīng)用這個(gè)插件
//在 app 下的 build.gradle 引用這個(gè)插件
apply plugin: PluginTest
- 5窟蓝、驗(yàn)證效果
app module 引用了這個(gè) PluginTest 插件罪裹,因此 app 這個(gè) project 就有 MyTask 這個(gè)任務(wù)了,我們來(lái)執(zhí)行一下驗(yàn)證一下效果吧运挫。
./gradlew :app:MyTask
好了状共,通過(guò)上面幾個(gè)步驟,就可以創(chuàng)建一個(gè)簡(jiǎn)單的 Gradle Plugin 工程了谁帕,但是回想一下峡继,我們新建一個(gè)工程之后,在 build.gradle 中匈挖,Gradle 會(huì)幫我們引用 Android 插件apply plugin: 'com.android.application'
碾牌,它們引用方式就跟我們上面引用方式是不一樣哦。
那這種引用方式是怎么定義的呢儡循?
這里其實(shí)是給我們的 Plugin 起了個(gè)別名舶吗,然后在外部就是用這個(gè)別名來(lái)引用。接下來(lái)我們通過(guò)源碼來(lái)看看'com.android.application'`是怎么定義的择膝?
【舉例】Gradle Android Plugin 中定義了一個(gè)叫 AppPlugin
的插件誓琼,這個(gè)插件是 Gradle 插件對(duì) Android 的擴(kuò)展,內(nèi)部定義 Android 相關(guān)的一些東西肴捉,例如 我們所熟知 android{}
內(nèi)部的東西都是屬于 Gradle 插件對(duì) Android 的擴(kuò)展腹侣。詳細(xì)的內(nèi)容可以參考另一篇博客:從源碼角度分析 Gradle 插件對(duì) Android 的擴(kuò)展
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.plugin"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
而這個(gè) AppPlugin
就是 build.gradle
引入 apply plugin: 'com.android.application'
,查看源碼齿穗,這個(gè)別名是定義在一個(gè)文件名
上的傲隶,文件內(nèi)容對(duì)這個(gè) AppPlugin 的映射關(guān)系。
那么我們依樣畫(huà)葫蘆缤灵,我們也來(lái)定義一下我們插件的別名吧:
下面來(lái)看一下如何來(lái)聲明我們自己的 Plugin ID 的
- 1伦籍、如下圖所示在
src/main/resources/META-INF.gradle-plugins
文件夾下創(chuàng)建文件
因?yàn)椴寮?lèi)的包名為 com.example.buildsrc ,所以該文件明就是
包名.properties
- 2、文件內(nèi)容
文件內(nèi)容的 implementation-class 對(duì)應(yīng)的值為
插件類(lèi)的全限名稱(chēng)
腮出。
implementation-class=com.example.buildsrc.PluginTest
- 3帖鸦、引用插件
在 app 下的 build.gradle 引用這個(gè)插件
apply plugin:'com.example.buildsrc'
- 4、驗(yàn)證效果
app module 引用了這個(gè) PluginTest 插件胚嘲,因此 app 這個(gè) project 就有 MyTask 這個(gè)任務(wù)了作儿,我們來(lái)執(zhí)行一下驗(yàn)證一下效果吧。
./gradlew :app:MyTask
好了馋劈,就這樣攻锰,我們也可以像引用 Android Gradle Plugin ID 一樣來(lái)引用我們自己的插件咯。
三妓雾、插件擴(kuò)展 Extension
什么是擴(kuò)展插件娶吞?
擴(kuò)展插件 Extension 就是用于 Plugin 與 Project
通訊
用的。
【舉例】我們想在 build.gradle 中通過(guò)配置 Extension 相關(guān)的屬性 械姻,然后將 Extension 這個(gè)對(duì)象傳遞給我們自定義的 Plugin妒蛇。
下面我們還是基于 PluginTest
這個(gè)插件來(lái)定義一個(gè)簡(jiǎn)單的插件擴(kuò)展。
- 1楷拳、定義
TestExtension
類(lèi)
我這里定義的是 Groovy Bean
(跟 Java Bean 類(lèi)似)绣夺,內(nèi)部定義一個(gè) message
變量。
class TestExtension {
String message;
}
- 2欢揖、 將 TestExtension 添加到 project#extensions 集合中陶耍。
class TestPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
//TestExtension extension = project.getExtensions().create("testExt", TestExtension)
//1.添加插件擴(kuò)展到project.extensions集合中
project.extensions.add("testExt", TestExtension)
project.task("TestTask") {
doLast {
//2.獲取外界配置的 TestExtension
TestExtension extension = project.testExt
//3.輸出插件擴(kuò)展屬性
println ">>>>>>" + extension.message
}
}
}
}
- 3、 給插件擴(kuò)展屬性賦值
//build.gradle
//依賴(lài)我們定義的插件
apply plugin: 'com.example.plugin.extension'
testExt {
//給插件擴(kuò)展的屬性賦值
message "helloworld"
}
- 4她混、 測(cè)試驗(yàn)證
./gradlew :app:TestTask
> Task :app:TestTask
當(dāng)前執(zhí)行的 Task TestTask
>>>>>>helloworld
插件擴(kuò)展在 Project 和 Plugin 之前傳遞數(shù)據(jù)如圖所示
# 參考
記錄于 2019年2月23日