Gradle是一個構建工具,既然是一個構建工具,那麼在構建項目的時候肯定有它生命週期,Gradle插件可以在指定的生命週期中插入一些自定義的邏輯,從而實現在項目的構建過程中完成我們想要的功能。Android中常見的 'apply plugin: 'com.android.application',其實引入的就是一個Google爲我們開發好的插件
一、Gradle構建的生命週期
在講解Gradle插件之前,先來看看Gradle的構建生命週期是怎麼樣的
1.Gradle構建的三個生命週期階段
-
初始化階段:讀取setting.gradle, 分析出項目包含的project及其他配置
-
配置階段:遞歸配置根項目和下面的子項目,主要涉及配置分析即task構建,最後生成task依賴有向圖
-
執行階段:執行task
用一張圖表示如下(引用於網絡)
2.關於Project
Project在Gradle中代表一個工程module,其實它相當於Java中的一個類,在Android中每一個子模塊都是一個project,同時根項目也是一個project,即每一個build.gradle對應一個project,Project提供的生命週期方法有:
//在 Project 進行配置前調用
void beforeEvaluate(Closure closure)
//在 Project 配置結束後調用
void afterEvaluate(Closure closure)
beforeEvaluate 必須在父模塊的 build.gradle 對子模塊進行配置才能生效,因爲在當前模塊的 build.gradle 中配置,它自己本身都沒配置好,所以不會監聽到
3.Gradle的其他生命週期回調方法
Gradle 提供了很多生命週期回調方法,如下所示
//在project進行配置前調用,child project必須在root project中設置纔會生效,
//root project必須在settings.gradle中設置纔會生效
void beforeProject(Closure closure)
//在project配置後調用
afterProject(Closure closure)
//構建開始前調用
void buildStarted(Closure closure)
//構建結束後調用
void buildFinished(Closure closure)
//所有project配置完成後調用
void projectsEvaluated(Closure closure)
//當settings.gradle中引入的所有project都被創建好後調用
//只在該文件設置纔會生效
void projectsLoaded(Closure closure)
//settings.gradle配置完後調用,只對settings.gradle設置生效
void settingsEvaluated(Closure closure)
4.Gradle的Task相關生命週期
Task在Gradle中代表一個任務,Gradle在構建項目的時候首先形成一個一個的Task,所有是Task形成了一個有向無環結構的模式,然後先後執行所有的Task,最後實現了整個項目的構建,gradle也可以對task的執行生命週期進行監聽
//任務執行前掉用
void afterTask(Closure closure)
//任務執行後調用
void beforeTask(Closure closure)
//任務準備好後調用
void whenReady(Closure closure)
上面是Gradle相關的生命週期方法, 理解這些對我們自定義Gradle插件非常重要
二、採用Groovy自定義Gradle插件
下面以自定義一個規範Android項目配置相關的Gradle插件爲例,講解一下實現Gradle插件的過程。首先新建一個Java Library module,在這裏命名爲CommConfigPlugin,刪除 src->main 下面的java目錄,新建一個groovy目錄,在groovy目錄下創建package;然後在 src->main 下面創建一個 resources 目錄,在resources目錄下創建 META-INF/gradle-plugins 目錄,最後在該目錄下創建一個名爲 com.config.plugin.properties的文件,文件名 com.config.plugin其實就是當前插件的名字,這個可以靈活定義,上面這些步驟就是創建Gradle插件的固定套路,形成的目錄結構如下
修改插件module的build.gradle文件,主要是引入groovy創建和依賴Gradle API,如下
此插件的開發背景:大家在開發項目的過程中,是不是都要配置編譯相關的SDK參數:compileSdkVersion、miniSdkVersion、targetSdkVersion,分別是Android編譯、最小、目標SDK版本的大小。通常在組件化開發的過程中,每個子項目和主項目需要統一這些SDK的版本大小,在這裏我們通過Gradle插件來檢測這些SDK版本大小並做一個規範,下面來看看如何實現
1.實現Plugin接口
編寫一個插件首先要做的是實現Plugin接口,如下
/**
* 配置相關規範插件
*/
class ConfigPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
println("執行插件configplugin")
//檢查Android編譯配置
CompileConfigUtil.checkCompileConfig(project)
}
}
當我們引用這個插件的時候,就會調用接口的apply方法,所以在apply方法中定義我們想要的邏輯,上面把檢測編譯配置的代碼封裝在CompileConfigUtil中,來看看
static def MIN_SDK = 19
static def TARGET_SDK = 28
static def COMPILE_SDK = "android-28"
/**
* 檢查編譯相關
* @param project
*/
static void checkCompileConfig(Project project) {
project.afterEvaluate {
BaseExtension android = project.extensions.getByName("android")
//強制統一 compileSdkVersion、 minSdkVersion、targetSdkVersion
String compileSdkVersion = android.compileSdkVersion
int targetSdkVersion = android.defaultConfig.targetSdkVersion.apiLevel
int minSdkVersion = android.defaultConfig.minSdkVersion.apiLevel
if (!COMPILE_SDK.equals(compileSdkVersion)) {
throw new GradleException("請修改 compileSdkVersion,必須設置爲 ${COMPILE_SDK}")
}
if (minSdkVersion != MIN_SDK) {
throw new GradleException("請修改 minSdkVersion,必須設置爲 ${MIN_SDK}")
}
if (targetSdkVersion != TARGET_SDK) {
throw new GradleException("請修改 targetSdkVersion,必須設置爲 ${TARGET_SDK}")
}
}
}
其實很簡單,就是在當前Project配置完以後在回調方法afterEvaluate中,首先獲取到"android"這個擴展Extension,然後進一步取得當前Project配置的編譯相關的sdk版本號,通過與規定的sdkversion對比,如果不符合規範則拋出異常,項目編譯不通過
2.使用Gradle插件
上面定義了一個簡單的gradle插件,下面來看看如何使用一個插件,在本項目我將定義的好的插件上傳到本地maven中,然後進行引用測試
在定義插件的module的build.gradle文件中加入maven相關配置
apply plugin: 'maven'
//通過maven將插件發佈到本地的腳本配置,根據自己的要求來修改
uploadArchives {
configuration = configurations.archives
repositories.mavenDeployer {
/*本地倉庫地址,注意:在編譯此項目的時候,你要換成你自己的地址或按照這個地址在你的電腦上創建對應的文件夾*/
repository(url: uri('file:\\G:\\MyLocalMaven\\repository')) /*倉庫地址*/
pom.project {
name 'configplugin-library' /*項目的名稱*/
description 'gradle插件' /*描述*/
groupId "com.lxr.maven" /*項目的倉庫路徑*/
artifactId "configplugin" //項目名稱
version '1.1.1' //版本號
}
}
}
點擊sync now,然後在Android studio 右側的Gradle目錄中找到一個uploadArchives的task,點擊
這樣在我們的插件就上傳到指定的本地位置了,如下
然後在根目錄的build.gradle文件中配置如下
最後在app工程的build.gradle文件中引用當前gradle插件進行測試
點擊sync now,出現如下情況
可以看到編譯被停止,因爲在此插件中,我們規定了miniSdkVersion爲19,而在app工程中定義的是17,所以編譯不通過,這就實現了通過插件自動檢測項目配置是否符合規範的功能
最後貼出項目的GitHub地址:https://github.com/jiusetian/EasyGradlePlugin