前面兩篇瞭解了Gradle的基礎知識,最終目的就是爲了自己能寫出Gradle插件來解決現實項目中的問題。現在Gradle自定義插件用的越來越廣泛,插件化,熱修復,性能優化,指標檢測,多渠道打包等等都會用到Gradle插件。
自定義Gradle插件的方式有三種,代碼都差不多,都是必須實現Plugin<T>
這個接口,然後實現接口中的apply
方法。只不過寫的地方不一樣。
第一種在build.gradle
在AndroidStido中創建一個新項目,然後直接在app目錄下的build.gradle文件中寫插件
class MyPlugin implements Plugin<Project>{
@Override
void apply(Project target) {
println('MyPlugin執行了')
target.task("mytask"){
doLast {
println('MyPlugin中的task執行了')
}
}
}
}
定義一個MyPlugin插件實現Plugin接口。然後在apply方法中自定義一個task。一個簡單的插件就完成了。
然後在當前build.gradle文件中引入插件
apply plugin: MyPlugin
OK完成,然後在控制檯執行一下我們自己的task,window下命令:gradlew mytask
輸出如下,Mac在gradlew前面加個./
> Configure project :app
MyPlugin執行了
> Task :app:mytask
MyPlugin中的task執行了
使用這種方式可以很快的創建一個插件,不過缺點也很明顯:
- 該plugin只能被當前build.gradle引用。
- 一個插件不可能就上面那幾行代碼,插件代碼全寫到這一個文件中,會讓這個文件非常臃腫不好維護。
第二種在buildSrc文件夾下
buildSrc是Gradle中的默認插件目錄,編譯的時候Gradle會自動識別這個目錄,將其內的代碼編譯成插件。
可以先創建一個java的module,然後修改一個build.gradle文件爲下面
apply plugin: 'groovy'
只寫上面的一句話就行。因爲需要寫一個groovy項目,所以把main文件夾下的原來的java入口文件夾直接改成groovy,這種方式比較方便。
或者重新建一個groovy文件夾,然後把這個文件夾設置爲項目的入口文件設置方式如下
sourceSets {
main {
groovy {
srcDir 'src/main/groovy'
}
}
}
然後開始在groovy文件夾下寫插件代碼 com.hsm.buildsrc.MyPlugin
class MyPlugin implements Plugin<Project> {
@Override
void apply(Project target) {
println('buildSrc中MyPlugin執行了')
target.task("mytask"){
doLast {
println('buildSrc中MyPlugin中的task執行了')
}
}
}
}
寫完插件,怎麼讓gradle知道哪個是插件呢?
- 在main目錄下新建resources目錄,然後在resources目錄裏面再新建META-INF目錄,再在META-INF裏面新建gradle-plugins目錄。最後在gradle-plugins目錄裏面新建properties文件
- properties文件的名字可以隨便取,後面用到的時候就用這個取好的名字,這裏就直接使用插件的包名了
com.hsm.buildsrc
。在properties文件中指明我們自定義的插件的類implementation-class=com.hsm.buildsrc.MyPlugin
然後去app中的build.gradle文件中引入插件
apply plugin: 'com.hsm.buildsrc'
最後控制檯輸入命令驗證插件gradlew mytask
> Configure project :app
buildSrc中MyPlugin執行了
> Task :app:mytask
buildSrc中MyPlugin中的task執行了
使用這種方式寫的插件,整個工程中的所有module都可以引用到,而且插件代碼在自己的文件夾中,也方便維護。
第三種自定義module,上傳maven
第二種方式寫的插件只能在當前工程中使用,有時候我們需要插件能多個工程都能使用,比如我們的項目中可以使用butterknife的插件,可以使用greenDao的插件。這就需要把我們的插件上傳到別的倉庫中比如maven。
在項目中新建一個module,這裏命名爲plugin_module,可以是java module也可以是android Library反正最後都得改嘿嘿。最好建個java的改的少。
修改build.gradle文件爲下面
apply plugin: 'groovy'
apply plugin: 'maven'
dependencies {
//gradle sdk
implementation gradleApi()
//groovy sdk
implementation localGroovy()
}
//uploadArchives是將已經自定義好了插件打包到本地Maven庫裏面去,
//也可以選擇打包到遠程服務器中。其中, group和version是我們之後配置插件地址時要用到的。
group='com.hsm.plugin_module'
version='1.0'
uploadArchives {
repositories {
mavenDeployer {
//本地的Maven地址:當前工程下
repository(url: uri('./my-plugin'))
//提交到遠程服務器:
// repository(url: "http://www.xxx.com/repos") {
// authentication(userName: "admin", password: "admin")
// }
}
}
}
- dependencies中添加gradle sdk和groovy sdk之後,我們建的這個module就可以開發gradle的工程了。
- uploadArchives是將已經自定義好了插件打包到本地Maven庫裏面去,也可以選擇打包到遠程服務器中
- group和version是別的項目引用的時候使用的組名和版本號
開始編寫插件:
class MyPlugin implements Plugin<Project> {
@Override
void apply(Project target) {
println('plugin_module 中MyPlugin執行了')
target.task("mytask"){
doLast {
println('plugin_module中MyPlugin中的task執行了')
}
}
}
}
然後跟第二步中的步驟一樣創建resources目錄和resources下面的各個目錄和文件。這裏使用的包名是com.hsm.plugin_module
執行gradle命令上傳插件jar包到maven倉庫gradlew uploadArchives
,執行完之後jar包就上傳到了我們前面定義的./my-plugin下面,內容如下圖
最後去工程中使用插件
首先來到主工程的build.gradle文件夾下引入插件的倉庫和依賴
buildscript {
repositories {
maven {
//本地倉庫地址
url uri('D:/androiddemo/5/GradlePlugin/plugin_module/my-plugin')
}
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
////格式爲-->group:module:version
classpath 'com.hsm.plugin_module:plugin_module:1.0'
}
}
- 設置本地倉庫的地址
- 在dependencies中引入插件,格式爲group:module:version
然後去app文件夾下的build.gradle文件中引入插件
apply plugin: 'com.hsm.plugin_module'
到這裏就OK了,控制檯中輸入命令驗證:gradlew mytask
> Configure project :app
plugin_module 中MyPlugin執行了
> Task :app:mytask
plugin_module中MyPlugin中的task執行了
插件的擴展 Extension
我們在集成tinker的時候,會在build.gradle文件中配置tinkerPatch的各種參數比如oldApk ,useSign,buildConfig 等等, 這就是在配置插件中的參數或者屬性,而插件的擴展Extension就是用來把這些參數傳回插件中。
現在給第三步中的插件添加一個擴展Extension
在插件的module中新建一個實體類MyExtension
package com.hsm.plugin_module
class MyExtension {
int id
String name
}
然後去MyPlugin插件類中添加擴展
class MyPlugin implements Plugin<Project> {
@Override
void apply(Project target) {
println('plugin_module 中MyPlugin執行了')
//1.添加插件擴展到project.extensions集合中
target.extensions.add('myextension',MyExtension)
target.task("mytask"){
doLast {
println('plugin_module中MyPlugin中的task執行了')
//2.獲取外界配置的 TestExtension
MyExtension extension = target.myextension
//3.輸出插件擴展屬性
println ">>>>>> name: ${extension.name} id:${extension.id}"
}
}
}
}
- 通過project.extensions.add方法將自定義的實體添加到擴展中,並起個名字
- 可以通過起的名字拿到擴展的實體類
- 最後拿到類中的屬性
修改完之後重新上傳到maven,如果版本號沒變,最好先把倉庫以前的文件刪掉在上傳
上傳完成之後去項目app目錄下的build.gradle中使用
apply plugin: 'com.hsm.plugin_module'
myextension{
id 123
name 'chs'
}
控制檯中執行命令驗證:gradlew mytask
> Configure project :app
plugin_module 中MyPlugin執行了
> Task :app:mytask
plugin_module中MyPlugin中的task執行了
>>>>>> name: chs id:123
OK,Gradle創建插件的流程完畢,想要完成更加複雜的功能,只需要在該插件中定義各種各樣的task來完成不同的邏輯即可。