一、前言
上一篇學習瞭如何自定義 Gradle 插件,本篇我們來學習下 Android 對 Gradle 的擴展:Variants(變體)以及 Transform。通過擴展可以讓我們在自定義 Gradle 插件時做更多的事情。
二、Variants(變體)
2.1 Variants 是什麼
要理解 Variants 的作用,就必須先了解 buildType、flavor、dimension 與 variant 之間的關係。在 android gradle plugin V3.x 之後,每個 flavor 必須對應一個 dimension,可以理解爲 flavor 的分組,然後不同 dimension 裏的 flavor 會組合成一個 variant。示例代碼如下所示:
android {
...
defaultConfig {...}
//gradle 默認就有 debug 和 release 兩個 buildType
buildTypes {
debug{...}
release{...}
}
flavorDimensions "version"
productFlavors {
demo {
dimension "version"
}
full {
dimension "version"
}
}
}
根據上述配置 Gradle 會創建以下構建變體:
- demoDebug
- demoRelease
- fullDebug
- fullRelease
在 Android 對 Gradle 插件的擴展支持之中,其中最常用的便是利用變體(Variants)來對構建過程中的各個默認的 task 進行 hook。關於 Variants 共有 三種類型,如下所示:
- applicationVariants:只適用於 app plugin。
- libraryVariants:只適用於 library plugin。
- testVariants:在 app plugin 與 libarary plugin 中都適用。
2.2 Variants 的使用
我們來看看 applicationVariants 的使用,首先我們在 app.gradle 中配置 buildTypes、flavorDimensions、productFlavors 同上。然後,我們可以 使用 applicationVariants.all 在配置階段之後去獲取所有 variant 的 name 與 baseName。代碼如下所示:
最後我們來執行下 gradle clean 任務:
可以看到,name 與 baseName 的區別:demoDebug 與 demo-debug 。
接下來我們來看看使用 applicationVariants.all 在配置階段之後去修改輸出的 APK 名稱:
可以看到,我們上面用到了一個 releaseTime() 方法獲取當前時間:
最後我們來執行以下 gradle clean:
可以看到正常修改了 apk 的名稱。
最後我們來看一下如何對 applicationVariants 中的 Task 進行 Hook,我們可以在 android.applicationVariants.all 的閉包中通過 variant.task 來獲取相應的 Task。代碼如下所示:
然後,執行 gradle clean,其輸出信息如下所示:既然可以獲取到變體中的 Task,我們就可以根據不同的 Task 類型來做特殊處理。例如,我們可以利用 variants 去解決插件化開發中的痛點:編寫一個對插件化項目中的各個插件自動更新的腳本,其核心代碼如下所示:
至於 update_plugin 的實現,主要就是一些插件安全校驗與下載的邏輯,這部分其實跟 Gradle 沒有什麼聯繫。
variant 中能獲取到哪些 task 我們可以去 ApplicationVariant 的父類 BaseVariant 中去查看,比如:
2.3 Gradle 構建流程
在執行 Android 項目的構建流程,可以發現沒有任何修改的情況下就已經有 30 多個Task需要執行:
其中關鍵的 task 如下:
三、Transform