Android?Gradle?插件自定義Plugin實現(xiàn)注意事項
Android Gradle Plugin
在 Android 項目中的 build.gradle 文件中,經(jīng)??梢钥匆娨恍?plugin 聲明:
plugins { id 'com.android.application' id 'com.android.library' } // or apply plugin: 'com.android.application' apply plugin: 'com.android.library'
上面是兩種引用 gradle 插件的常用代碼,com.android.application
是用來構(gòu)建 apk 的 gradle 插件;com.android.library
是用來構(gòu)建 Android Library 的 gradle 插件。
Gradle 是什么?
Gradle 是自動化構(gòu)建工具,多項目構(gòu)建而設(shè)計的。通過 groovy 或 kotlin 來編寫構(gòu)建腳本。主要用來處理:
- 自動處理包依賴關(guān)系
- 自動處理部署問題
過去 Java 開發(fā)者常用 Maven 和 Ant 等工具進行封裝布署的自動化,或是兩者兼用,不過這兩個包彼此有優(yōu)缺點:
- 如果頻繁改變相依包版本,使用 Ant 相當(dāng)麻煩,
- 如果瑣碎工作很多,Maven 功能不足
- 而且兩者都使用 XML 描述,相當(dāng)不利于設(shè)計 if、switch 等判斷式,即使寫了可讀性也不佳
而 Gradle 改良了過去 Maven、Ant 帶給開發(fā)者的問題,至今也成為 Android Studio 內(nèi)置的封裝布署工具。
官方文檔:What is Gradle?
Gradle 插件
Gradle 的核心是提供自動化處理流程。所有有用的特性,比如編譯 Java 代碼的能力,都是由插件添加的。
插件實際的作用有:
- 拓展 Gradle Model (例如:添加可配置的新 DSL 元素)
- 根據(jù)約定配置項目(例如:添加新的 Gradle Task 或配置一些合理的默認(rèn)值)
- 應(yīng)用指定的配置(例如:添加一些倉庫或執(zhí)行標(biāo)準(zhǔn))
好處:
通過應(yīng)用插件,而不是向項目構(gòu)建腳本添加邏輯,可以獲得的好處有:
- 提高復(fù)用能力,減少跨多個項目維護類似邏輯的開銷:同一個插件可以應(yīng)用到不同的項目。
- 更好的模塊化:通過插件的形式,可以使項目架構(gòu)更加明確更容易理解。
- 封裝重要的邏輯,允許構(gòu)建腳本盡可能具有聲明性。
分類
Gradle 插件有兩種類型,分為二進制插件和腳本插件。
二進制插件:
- 二進制插件可以通過實現(xiàn)
org.gradle.api.Plugin
接口以編程方式編寫,也可以使用 Gradle 的一種 DSL 語言以聲明方式編寫。 - 二進制插件可以駐留在構(gòu)建腳本中、項目層次結(jié)構(gòu)中或外部插件 jar 包中。
腳本插件:
- 腳本插件是額外的構(gòu)建腳本,可以進一步配置構(gòu)建并且通常實現(xiàn)一種聲明性的方法來操作構(gòu)建。它們通常在構(gòu)建中使用,盡管它們也可以外部化并從遠(yuǎn)程位置訪問。
- 插件通常以腳本插件開始(因為它們易于編寫),然后隨著代碼變得更有價值,它被遷移到可以在多個項目或組織之間輕松測試和共享的二進制插件。
使用插件
要使用插件中封裝的構(gòu)建邏輯,Gradle 需要執(zhí)行兩個步驟。 首先,解析插件,然后需要將插件應(yīng)用到一個目標(biāo)上,通常是一個 org.gradle.api.Project
對象。
- 解析插件:解析插件的工作是找到包含給定插件的正確版本的 jar 并將其添加到腳本類路徑中。一旦一個插件被解析,它的 API 就可以在構(gòu)建腳本中使用。
- 應(yīng)用插件:應(yīng)用插件意味著在要使用插件的項目上實際執(zhí)行插件的
Plugin.apply(T
。應(yīng)用插件是冪等的。也就是說,您可以安全地多次應(yīng)用任何插件而不會產(chǎn)生副作用。
本篇文章主要介紹如何實現(xiàn)一個二進制插件。
實現(xiàn)一個插件
最簡單的構(gòu)建 Gradle 插件的方式是 通過命令來構(gòu)建:
gradle init // or ./gradlew init
執(zhí)行命令:
- 第一步,選擇項目類型,4 是 Gradle 插件項目。
- 第二步,選擇實現(xiàn)芋圓,這里主要是 插件的代碼語言,支持 Groovy、Java 和 Kotlin。
- 第三步,選擇 DSL 語言(構(gòu)建腳本語言),支持 Groovy 和 Kotlin。
- 第四步,輸入項目名稱和插件包名。
最后會顯示構(gòu)建結(jié)果。 構(gòu)建完的項目結(jié)構(gòu)是這樣的:
這里有很多不需要的文件目錄,包括用來測試和 Gradle 的一些相關(guān)內(nèi)容,都可以刪除(當(dāng)然你也可以不處理),因為當(dāng)我們把這個項目引入到一個 Android 項目中時,Android 項目提供了 Gradle 相關(guān)文件。
如圖所示,ExamplePlugin 目錄下 gradle 相關(guān)的文件,在 Android 的根目錄中都存在。 其中構(gòu)建插件相關(guān)的內(nèi)容都在 build.gradle 文件中,首先是,插件項目引用的插件:
plugins { id 'java-gradle-plugin' id 'maven' // maven 倉庫 id 'groovy' // groovy 支持 }
需要重點注意的是,使用一些第三方依賴如果下載不到,要檢查引用的遠(yuǎn)程倉庫是否在包含想要引用的依賴:
repositories { // Use JCenter for resolving dependencies. jcenter() }
當(dāng)我想引用 com.android.tools.build:gradle
依賴時,一直報錯,原因是 jcenter 中不存在這個項目,需要添加 google()
。
然后是一些依賴:
dependencies { // ... testImplementation 'org.spockframework:spock-core:1.3-groovy-2.5' }
接下來是比較重要的插件定義:
gradlePlugin { // Define the plugin plugins { customName { id = 'com.example.plugin.customname' implementationClass = 'com.example.plugin.ComExamplePluginPlugin' } } }
這里需要注意的是 customName 是你可以隨意定義的字符串,這個字符串會在 Plugin.apply 方法中使用到。 Id 就是插件唯一標(biāo)識,后續(xù)在其他項目中引用的時候,也是引用這個 id 。 implementationClass 的值指向一個實際的代碼類,這個類實現(xiàn)了 org.gradle.api.Plugin
。 自動生成的 Plugin 實現(xiàn)類是這樣的:
class ComExamplePluginPlugin implements Plugin<Project> { void apply(Project project) { // Register a task project.tasks.register("customName") { doLast { println("Hello from plugin 'com.example.plugin.customname'") } } } }
在這個 apply 方法中,使用之前我們定義的 customName 注冊了一個 Task 。 實際上 Gradle 后續(xù)就是執(zhí)行這個 Task ,來執(zhí)行代碼塊中的代碼的。
在很多之前的 Gradle 插件實現(xiàn)方案中,需要創(chuàng)建 resources/META-INF/gradle-plugin/xxx.properties
,而通過上面的方式,不需要在去創(chuàng)建這個文件了。 這樣一個插件的定義基本上就完成了。
發(fā)布插件
我們已經(jīng)定義好了一個 Gradle 插件,那么應(yīng)該如何校驗這個插件是否真的能夠使用呢?為了解決這個問題,我們要把 Gradle 插件發(fā)布到遠(yuǎn)程倉庫或者本地目錄,然后供其他項目引用,以此來測試插件。 以本地發(fā)布為例,在插件項目的根目錄下的 build.gradle
文件中添加:
plugins { // ... id 'maven-publish' // 用來發(fā)布插件 } publishing { repositories { maven { // $rootDir 表示你項目的根目錄 // 這里配置發(fā)布到的本地目錄 url = "$rootDir/repo" } } publications { publish(MavenPublication) { // 插件的組ID,建議設(shè)置為插件的包名 groupId = 'com.example.plugin.customname' // 插件的名字,后續(xù)在引用時會用到 artifactId = 'customName' version = '0.0.1' // 組件類型 from components.java } } }
如果發(fā)布到本地,運行 Gradle 命令:
./gradlew publishPublishPublicationToMavenLocal
則會發(fā)布到本地目錄 /Users/XXX/.m2/repository/
中。
./gradlew publishPublishPublicationToMavenRepository
會發(fā)布到你在 build.gradle
中,指定的目錄 "$rootDir/repo"
中。
引用插件
在 Android 項目中引用的第一步是在根目錄的 build.gradle
中添加 maven 倉庫,這樣 Gradle 才能從特定的本地目錄中找到我們的 jar 包:
repositories { jcenter() google() maven { url = "$rootDir/repo" } }
第二步,在根目錄的 build.gradle
中添加依賴:
dependencies { classpath "com.example.plugin.customname:customName:0.0.1" }
這個就是我們在發(fā)布插件時,指定的 groupId 、artifactId 和 version,規(guī)則是:
classpath "$groupId:$artifactId:$version"
然后,在需要引用的 module 下的 build.gradle
文件中應(yīng)用插件:
plugins { id 'com.example.plugin.customname' }
這里的 id 是我們在定義插件時在 gradlePlugin 代碼塊中指定的。 這樣我們就成功的通過 jar 包的形式引用到了插件。 這里以我另一個項目為例,我在 gradlePlugin 中指定的代碼塊自定義名稱為 transfrom :
gradlePlugin { plugins { transform { // ... } } }
引用成功后會在 Gradle Task 中多一個同名的任務(wù):
對應(yīng)的 Groovy 中實現(xiàn) apply 方法:
@Override void apply(Project project) { project.tasks.register("transform") { doLast { println("Hello from plugin 'com.chunyu.transform.plugin'") } } }
執(zhí)行該任務(wù),會看到 log 面板中有對應(yīng)的輸出:
> Task :app:transform
Hello from plugin 'com.chunyu.transform.plugin'
成功的驗證了,在 apply 中 print 代碼正確的執(zhí)行了。
到此這篇關(guān)于Android Gradle 插件自定義Plugin實現(xiàn)注意事項的文章就介紹到這了,更多相關(guān)Android Gradle 插件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android 開發(fā)使用PopupWindow實現(xiàn)彈出警告框的復(fù)用類示例
這篇文章主要介紹了Android 開發(fā)使用PopupWindow實現(xiàn)彈出警告框的復(fù)用類,結(jié)合實例形式分析了Android基于PopupWindow彈出警告框的復(fù)用類具體布局與功能實現(xiàn)技巧,需要的朋友可以參考下2020-05-05Android編程解析Json格式數(shù)據(jù)的方法
這篇文章主要介紹了Android編程解析Json格式數(shù)據(jù)的方法,涉及Android中json格式數(shù)據(jù)的構(gòu)造、讀取及遍歷等技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-11-11Android開源項目PullToRefresh下拉刷新功能詳解2
這篇文章主要為大家進一步的介紹了Android開源項目PullToRefresh下拉刷新功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09深入解析Android App的LayoutInflate布局
這篇文章主要介紹了Android App的LayoutInflate布局,對LayoutInflate編寫中經(jīng)常被無解及產(chǎn)生錯誤的地方進行了深入說明,需要的朋友可以參考下2016-04-04