最近需要做了一個功能泳赋,需要將Android工程中的一個lib庫中所依賴的aar诽俯、jar等直接都打包,在最后的生成產(chǎn)物中-aar包含以上所有的依賴庫呛占;我們在開發(fā)Android過程中虑乖,也會遇到對編譯過程進行干擾;當前Android工程的開發(fā)都是基于Gradle進行構(gòu)建的晾虑,等等這些都要求對于Gradle我們需要進行一個比較全面的了解疹味。
什么是Gradle
Gradle是一個開源的構(gòu)建腳本工具,能夠協(xié)助大家更好的提高開發(fā)效率帜篇;Gradle的構(gòu)建腳本都是使用Groovy或者Kotlin或者Java編寫的糙捺;Gradle提供了大量的API,我們可以根據(jù)這些API編寫出自己的工具(Plugin-插件工具)笙隙,利用自己編寫的工具實現(xiàn)自己的需求洪灯,例如:復制文件、將特定文件目錄的java源代碼打包成jar包等竟痰。Gradle構(gòu)建工具在最后還是啟動了JVM签钩,幫助自己干事情掏呼。
Gradle初體驗
對于Gradle的安裝可以參考官方文檔,安裝完成以后我們可以使用 gradle init(對于IDE創(chuàng)建工程边臼,這個命令有IDE自己完成)命令初始化一個gradle構(gòu)建的工程哄尔,查看當前的文件目錄如下:
├── build.gradle
├── settings.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
這個就是使用gradle構(gòu)建一個工程必須的一些文件,這些文件的和我們創(chuàng)建的Android工程是不是有點類似呢柠并。接下來對這些文件的用途做一個簡單的介紹:
build.gradle:主要是為執(zhí)行的一些task配置一些參數(shù)岭接,或者在這里添加自己的參數(shù)等;對應與Android構(gòu)建工程中臼予,在該文件中配置了編譯時使用的sdk版本鸣戴、編譯工具版本等參數(shù);這里配置中最終要的一點就是需要使用哪些插件粘拾,使用了什么插件就是使用了哪些task窄锅;
setting.gradle:配置一下當前工程目錄中,哪些子工程需要參與構(gòu)建缰雇;
gralde:該目錄中包含了gradle-wrapper.jar和gradle-wrapper.properties兩個文件入偷,其中jar包就是一個可執(zhí)行的gradle,gradle-wrapper.properties主要是配置一些與這個可執(zhí)行jar包相關(guān)的參數(shù):
#Sun Mar 11 21:54:32 CST 2018
#分配的最基本的地址路徑械哟,主要是用于存儲gradle.jar
distributionBase=GRADLE_USER_HOME
#gradle.jar存儲的相對路徑疏之,與前面的基本路徑組合成了絕對路徑
distributionPath=wrapper/dists
#下載gradle.jar的zip類型文件存儲的基本路徑
zipStoreBase=GRADLE_USER_HOME
#zip文件存儲的相對路徑,與前面的基本路徑組合為絕對路徑
zipStorePath=wrapper/dists
#需要下載的對應版本gradl壓縮包
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip
gradlew與gradlew.bat:這兩個文件都是可執(zhí)行的腳本暇咆,功能都是相同的锋爪,只是對應不同系統(tǒng)下的執(zhí)行腳本,分別對應Unix base和Window系統(tǒng)爸业。執(zhí)行該腳本的功能與直接在命令行執(zhí)行g(shù)radle功能是相同的其骄,那這個腳本存在的意義是什么呢,主要的意義在于可以執(zhí)行特定版本的gradle扯旷,也就是上面gradle文件下的jar包拯爽,我們需要修改gradle-wrapper.properties下對應的屬性,并重新執(zhí)行g(shù)radlew腳本就會重新下載钧忽。
Gradle與插件
對于插件比較直觀的體驗就是安裝了插件我可以使用特定的功能某抓,例如在瀏覽器上安裝了Octotree,我們在瀏覽Github上的開源工程的時候惰瓜,可以在左側(cè)直接查看工程目錄。對于Gradle構(gòu)建的工程汉矿,如果我們需要使用某些特定功能的構(gòu)建工具崎坊,也是以插件的形式完成的。
插件的主要功能就是利用Gradle 定義的API實現(xiàn)自己的功能洲拇,前面已經(jīng)說過Gradle開放了大量的API奈揍,這些API主要是定義了基本的一些功能:copy文件曲尸、文件打包為jar包等;對于Android開發(fā)來說比較常見的插件有下面兩個:
//構(gòu)建Android App的插件
apply plugin: 'com.android.application'
//構(gòu)建Android Lib的插件
apply plugin: 'com.android.library'
其實上面的這些插件都是Android官方為廣大開發(fā)者提供的男翰,對于App構(gòu)建的過程有了解過的人肯定比較清晰的知道另患,里面包括了R.java文件的生成、dex文件的生成蛾绎、打包等昆箕;對于正常情況下如果不使用自動打包構(gòu)建腳本,我們肯定需要使用Android提供的最原生的工具aapt租冠、dx等按部就班的生成對應的文件和轉(zhuǎn)換鹏倘,最后打包壓縮為APK文件。但是使用這些構(gòu)建腳本可以大大提高我們的開發(fā)效率顽爹、發(fā)布效率纤泵、構(gòu)建效率等。
自定義Gradle插件-自己動手
在構(gòu)建自己的Gradle之前需要了解兩個基本的API接口镜粤,方便更好的理解自己編寫的Gradle插件捏题。
基本知識點
Project
在前面初步體驗Gradle的時候,簡單的創(chuàng)建了一個Gradle構(gòu)建工程肉渴,對于一個工程就對應與Gradle中的一個Project對象公荧,Project對象里面定義了大量與該工程對應的變量、操作方法等黄虱。我們在使用 gradle 工具構(gòu)建工程的時候會讀取目錄文件中的 build.gradle 文件稚矿,該文件配置了Project相關(guān)的屬性;
Task
對于一個工程來說捻浦,當需要構(gòu)建的時候肯定需要一步一步的完成某些步驟晤揣,最后產(chǎn)生自己需要的產(chǎn)物;對于Gradle構(gòu)建來說朱灿,把這些一個一個的步驟對應了一個Task對象昧识;還是以Android打包過程來進行分析,如果我們需要將當前的java原文件編譯成class文件盗扒,這里就需要使用cmpileJava這個Task跪楞;對于Android打包的插件也就是定義了大量的Task,然后將這些Task添加到Project中侣灶,并定義好它們的順序甸祭,在構(gòu)建腳本啟動的時候按照先前定義好的順序,逐個執(zhí)行這些Task褥影,最終就會得到我們自己想要的產(chǎn)物—APK文件池户。
開始自定義
下面就開始來編寫自己的插件,并執(zhí)行運行該插件。首先需要創(chuàng)建一個Gradle構(gòu)建工程校焦,直接使用 gradle init 命令創(chuàng)建了我們在第一部分的工程目錄:
├── build.gradle
├── settings.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
然后使用如下命令創(chuàng)建目錄:
mkdir -p buildSrc/src/main/java/com/github/songnick/example
然后創(chuàng)建文件:buildSrc/src/main/java/com/github/songnick/example/ExamplePlugin.java
package com.github.songnick.example;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
public class ExamplePlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getTasks().create("hello", HelloTask.class, (task) -> {
task.setMessage("Hello");
task.setRecipient("World");
});
}
}
這里是實現(xiàn)了插件接口赊抖,并重寫了apply方法,在該方法中使用project對象提供的接口定義了一個Task—HelloTask寨典,這里的project對象就是上面的部分介紹到的氛雪,可以通過這個project對象獲取工程構(gòu)建的文件目錄、依賴的庫等信息耸成。對于HelloTask類的具體定義如下:
buildSrc/src/main/java/com/github/songnick/example/HelloTask.java
package com.github.songnick.example;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;
public class HelloTask extends DefaultTask {
private String message;
private String recipient;
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public String getRecipient() { return recipient; }
public void setRecipient(String recipient) { this.recipient = recipient; }
//具體的任務執(zhí)行注解
@TaskAction
void sayGreeting() {
System.out.printf("%s, %s!\n", getMessage(), getRecipient());
}
}
這里的@TaskAction注解表示最后調(diào)用這個任務的執(zhí)行方法报亩;
當我們創(chuàng)建和編寫完成上面的文件以后,當前的文件目錄結(jié)構(gòu)就變?yōu)榱耍?/p>
├── build.gradle
├── buildSrc
│ └── src
│ └── main
│ └── java
│ └── com
│ └── github
│ └── songnick
│ └── example
│ ├── ExamplePlugin.java
│ └── HelloTask.java
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
多出了buildSrc文件目錄及里面的文件墓猎,這個時候直接執(zhí)行 gradle命令或者./gradlew 這個時候就會編譯buildSrc文件下的java文件捆昏,并生成了編譯過后相關(guān)的產(chǎn)物,可以通過buildSrc/build/文件目錄去查看對應的產(chǎn)物毙沾,其中包括class文件骗卜、jar包等。這里有可能比較疑惑左胞,為什么執(zhí)行這個命令會編譯buildSrc文件下對應的文件寇仓,這個是gradle工具在執(zhí)行構(gòu)建的時候默認會把當前文件目錄下的buildSrc文件作為自己的默認編譯目錄。現(xiàn)在我們編譯完成了烤宙,怎么驗證我們編寫的插件是否能夠正常使用呢遍烦,用編輯器打開當前目錄中的build.gradle文件,并添加如下字段:
apply plugin: com.github.songnick.example.ExamplePlugin
然后執(zhí)行 ./gradlew tasks 結(jié)果中會看到:
Other tasks-----------hello
這里就是我們通過自定義的插件添加的Task-名字叫hello躺枕;我們可以直接執(zhí)行該task:./gradlew hello 查看結(jié)果服猪。
上面是通過自己在命令行純手工實現(xiàn)了一個自定義的插件以及Task,當然也可以通過其他IDE創(chuàng)建插件工程拐云,并實現(xiàn)發(fā)布等罢猪,這些對應的教程也比較多,這里就不詳細介紹叉瘩。主要是希望通過上面簡單的創(chuàng)建過程大家可以直接的感受一下自定義插件膳帕。
構(gòu)建Gradle插件-編程語言
上面自定義插件的部分中,我們使用了Java語言編寫了相關(guān)接口的實現(xiàn)薇缅、類的繼承等危彩;其實對于插件的編寫Gradle構(gòu)建工具還支持Groovy,對于語言來說我們不需要糾結(jié)太多泳桦,每個語言都有其特點汤徽;那么Gradle為啥要支持除了Java語言的Groovy語言呢,我個人的理解其實很簡單灸撰,可以從Android工程使用Gradle構(gòu)建看出谒府,我們需要對工程做一些配置漆羔,這些配置都是放在 build.gradle 中,我們發(fā)現(xiàn)在配置這些參數(shù)的時候就是使用了Groovy語言的特性狱掂。對于Groovy語言是DSL(領(lǐng)域?qū)S谜Z言),這些語言的設(shè)計初衷是給非程序員使用亲轨,所以設(shè)計的時候就會更加的容易讓人理解趋惨,使用起來更方便;對于Grooy語言的學習大家可以自行學習惦蚊,這里就不過多的介紹了器虾。
后記
簡單的把Gradle的基礎(chǔ)的基本概念和自己的理解闡述 了一下,更多的學習資料還是直接訪問官網(wǎng)吧蹦锋,對于插件的編寫以及Groovy的學習可以直接學習Android構(gòu)建插件的源碼吧兆沙。