Gradle之自定義插件

前面兩篇瞭解了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執行了

使用這種方式可以很快的創建一個插件,不過缺點也很明顯:

  1. 該plugin只能被當前build.gradle引用。
  2. 一個插件不可能就上面那幾行代碼,插件代碼全寫到這一個文件中,會讓這個文件非常臃腫不好維護。

第二種在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來完成不同的邏輯即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章