Gradle基礎(chǔ)

最近需要做了一個功能,需要將Android工程中的一個lib庫中所依賴的aar、jar等直接都打包,在最后的生成產(chǎn)物中-aar包含以上所有的依賴庫;我們在開發(fā)Android過程中,也會遇到對編譯過程進行干擾;當(dāng)前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)自己的需求,例如:復(fù)制文件、將特定文件目錄的java源代碼打包成jar包等。Gradle構(gòu)建工具在最后還是啟動了JVM,幫助自己干事情。

Gradle初體驗

對于Gradle的安裝可以參考官方文檔,安裝完成以后我們可以使用 gradle init(對于IDE創(chuàng)建工程,這個命令有IDE自己完成)命令初始化一個gradle構(gòu)建的工程,查看當(dāng)前的文件目錄如下:

├── 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ù)等;對應(yīng)與Android構(gòu)建工程中,在該文件中配置了編譯時使用的sdk版本、編譯工具版本等參數(shù);這里配置中最終要的一點就是需要使用哪些插件,使用了什么插件就是使用了哪些task;
setting.gradle:配置一下當(dāng)前工程目錄中,哪些子工程需要參與構(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        
#需要下載的對應(yīng)版本gradl壓縮包
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip  

gradlew與gradlew.bat:這兩個文件都是可執(zhí)行的腳本,功能都是相同的,只是對應(yīng)不同系統(tǒng)下的執(zhí)行腳本,分別對應(yīng)Unix base和Window系統(tǒng)。執(zhí)行該腳本的功能與直接在命令行執(zhí)行g(shù)radle功能是相同的,那這個腳本存在的意義是什么呢,主要的意義在于可以執(zhí)行特定版本的gradle,也就是上面gradle文件下的jar包,我們需要修改gradle-wrapper.properties下對應(yīng)的屬性,并重新執(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等按部就班的生成對應(yīng)的文件和轉(zhuǎn)換,最后打包壓縮為APK文件。但是使用這些構(gòu)建腳本可以大大提高我們的開發(fā)效率、發(fā)布效率、構(gòu)建效率等。

自定義Gradle插件-自己動手

在構(gòu)建自己的Gradle之前需要了解兩個基本的API接口,方便更好的理解自己編寫的Gradle插件。

基本知識點

Project

在前面初步體驗Gradle的時候,簡單的創(chuàng)建了一個Gradle構(gòu)建工程,對于一個工程就對應(yīng)與Gradle中的一個Project對象,Project對象里面定義了大量與該工程對應(yīng)的變量、操作方法等。我們在使用 gradle 工具構(gòu)建工程的時候會讀取目錄文件中的 build.gradle 文件,該文件配置了Project相關(guān)的屬性;

Task

對于一個工程來說,當(dāng)需要構(gòu)建的時候肯定需要一步一步的完成某些步驟,最后產(chǎn)生自己需要的產(chǎn)物;對于Gradle構(gòu)建來說,把這些一個一個的步驟對應(yīng)了一個Task對象;還是以Android打包過程來進行分析,如果我們需要將當(dāng)前的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; }

    //具體的任務(wù)執(zhí)行注解
    @TaskAction
    void sayGreeting() {
        System.out.printf("%s, %s!\n", getMessage(), getRecipient()); 
    }
}

這里的@TaskAction注解表示最后調(diào)用這個任務(wù)的執(zhí)行方法;
當(dāng)我們創(chuàng)建和編寫完成上面的文件以后,當(dā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/文件目錄去查看對應(yīng)的產(chǎn)物,其中包括class文件、jar包等。這里有可能比較疑惑,為什么執(zhí)行這個命令會編譯buildSrc文件下對應(yīng)的文件,這個是gradle工具在執(zhí)行構(gòu)建的時候默認(rèn)會把當(dāng)前文件目錄下的buildSrc文件作為自己的默認(rèn)編譯目錄。現(xiàn)在我們編譯完成了,怎么驗證我們編寫的插件是否能夠正常使用呢,用編輯器打開當(dāng)前目錄中的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,當(dāng)然也可以通過其他IDE創(chuàng)建插件工程,并實現(xiàn)發(fā)布等,這些對應(yīng)的教程也比較多,這里就不詳細介紹。主要是希望通過上面簡單的創(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語言的學(xué)習(xí)大家可以自行學(xué)習(xí),這里就不過多的介紹了。

后記

簡單的把Gradle的基礎(chǔ)的基本概念和自己的理解闡述 了一下,更多的學(xué)習(xí)資料還是直接訪問官網(wǎng)吧,對于插件的編寫以及Groovy的學(xué)習(xí)可以直接學(xué)習(xí)Android構(gòu)建插件的源碼吧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,741評論 25 709
  • 什么是 Gradle ? 所謂構(gòu)建工具就是對你的項目進行編譯、運行、簽名、打包、依賴管理等一系列功能的合集,傳統(tǒng)的...
    方子晗閱讀 614評論 0 0
  • Gradle是基與Groovy的腳本配置的構(gòu)筑工具,用與構(gòu)筑Java及Android應(yīng)用. Gradle Grad...
    花京院典明閱讀 1,190評論 0 8
  • 突然又說到小時候, 想當(dāng)年我是多愛說話, 想當(dāng)年數(shù)學(xué)多簡單, 想當(dāng)年同學(xué)是多單純, 想當(dāng)年總喜歡表現(xiàn), 想當(dāng)年想哭...
    怎么都被用了呢閱讀 259評論 2 5
  • 追求美是一種人的本能,雖然每個人心目中的美不盡相同,追求美的方式也千奇百怪。黑夜為燈提供了綻放異彩的土壤,...
    霸王東渡閱讀 261評論 1 3

友情鏈接更多精彩內(nèi)容