Android 應用程式通常會使用 Gradle 建構系統進行建構。在深入探討如何設定版本的詳細資訊之前,我們將探索版本背後的概念,讓您能全面瞭解系統。
什麼是建構?
建構系統會將原始碼轉換為可執行的應用程式。建構作業通常會涉及多個工具,用於分析、編譯、連結及封裝應用程式或程式庫。Gradle 會使用以工作為基礎的方法來整理及執行這些指令。
Tasks 會封裝指令,將輸入內容轉換為輸出內容。外掛程式可定義工作及其設定。將外掛程式套用至建構作業會註冊其工作,並使用其輸入和輸出內容將這些工作連接在一起。舉例來說,將 Android Gradle 外掛程式 (AGP) 套用至建構檔案,即可註冊建構 APK 或 Android 程式庫所需的所有工作。java-library
外掛程式可讓您從 Java 原始碼建構 jar。Kotlin 和其他語言也有類似的外掛程式,但其他外掛程式旨在擴充外掛程式。舉例來說,protobuf
外掛程式可為 AGP 或 java-library
等現有外掛程式新增 protobuf 支援。
Gradle 偏好慣例而非設定,因此外掛程式會提供良好的預設值,但您可以透過宣告式特定領域語言 (DSL) 進一步設定建構作業。DSL 的設計目的是讓您指定要建構的內容,而非建構方式。外掛程式中的邏輯會管理「如何」處理。您可以在專案 (和子專案) 中的多個建構檔案中指定該設定。
工作輸入內容可以是檔案和目錄,以及以 Java 類型 (整數、字串或自訂類別) 編碼的其他資訊。輸出內容只能是目錄或檔案,因為它們必須寫入磁碟。將工作輸出內容連接至另一個工作輸入內容,即可將工作連結在一起,讓其中一個工作必須在另一個工作之前執行。
雖然 Gradle 支援在建構檔案中編寫任意程式碼和工作宣告,但這可能會讓工具更難瞭解您的建構作業,也讓您更難維護。舉例來說,您可以為外掛程式中的程式碼編寫測試,但無法在建構檔案中編寫測試。相反地,您應將建構邏輯和工作宣告限制在外掛程式 (由您或其他人定義) 中,並宣告要在建構檔案中使用該邏輯的方式。
Gradle 建構作業執行時會發生什麼事?
Gradle 建構作業分為三個階段。每個階段都會執行您在建構檔案中定義的不同程式碼部分。
- 初始化會判斷建構作業應納入哪些專案和子專案,並設定包含建構檔案和套用外掛程式的類別路徑。這個階段著重於設定檔,您可以在其中宣告要建構的專案,以及擷取外掛程式和程式庫的位置。
- 設定會為每個專案註冊工作,並執行建構檔案,以套用使用者的建構規格。請務必瞭解,設定程式碼無法存取執行期間產生的資料或檔案。
- 執行會執行應用程式的實際「建構」作業。設定檔的輸出內容是任務的有向非循環圖 (DAG),代表使用者要求的所有必要建構步驟 (在指令列上提供的任務,或在建構檔案中設為預設值)。這張圖表代表工作之間的關係,無論是工作宣告中明確指出,或是根據工作輸入和輸出內容,如果工作輸入內容是另一項工作的輸出內容,則必須在該工作之後執行。這個階段會依圖表中定義的順序執行過時的工作,如果工作輸入內容自上次執行後未變更,Gradle 就會略過該工作。
詳情請參閱 Gradle 建構生命週期。
設定 DSL
Gradle 會使用特定領域語言 (DSL) 設定建構作業。這種宣告式方法著重於指定資料,而非編寫逐步 (命令式) 指示。您可以使用 Kotlin 或 Groovy 編寫建構檔案,但我們強烈建議您使用 Kotlin。
DSL 可讓所有人 (包括領域專家和程式設計師) 更輕鬆地為專案做出貢獻,定義一種小型語言,以更自然的方式呈現資料。Gradle 外掛程式可以擴充 DSL,以便設定任務所需的資料。
舉例來說,設定建構的 Android 部分可能會如下所示:
Kotlin
android { namespace = "com.example.app" compileSdk = 34 // ... defaultConfig { applicationId = "com.example.app" minSdk = 34 // ... } }
Groovy
android { namespace 'com.example.myapplication' compileSdk 34 // ... defaultConfig { applicationId "com.example.myapplication" minSdk 24 // ... } }
在幕後,DSL 程式碼類似於以下內容:
fun Project.android(configure: ApplicationExtension.() -> Unit) {
...
}
interface ApplicationExtension {
var compileSdk: Int
var namespace: String?
val defaultConfig: DefaultConfig
fun defaultConfig(configure: DefaultConfig.() -> Unit) {
...
}
}
DSL 中的每個區塊都由函式表示,該函式會使用 lambda 進行設定,並使用同名屬性存取該函式。這樣一來,建構檔案中的程式碼就會更像資料規格。
外部依附元件
Maven 建構系統引入了依附元件規格、儲存空間和管理系統。程式庫會儲存在存放區 (伺服器或目錄) 中,中繼資料則包含版本資訊和對其他程式庫的依附元件。您可以指定要搜尋哪些存放區、要使用的依附元件版本,建構系統會在建構期間下載這些項目。
Maven 成果會透過群組名稱 (公司、開發人員等)、成果名稱 (程式庫名稱) 和成果版本來識別。通常會以 group:artifact:version
表示。
這種做法可大幅改善建構管理。您經常會聽到這類存放區稱為「Maven 存放區」,但這只是描述建構元素的封裝和發布方式。這些存放區和中繼資料已在多個建構系統中重複使用,包括 Gradle (Gradle 可發布至這些存放區)。公開存放區可供所有人使用,而公司存放區則可將內部依附元件保留在公司內部。
您也可以將專案模組化,轉換為子專案 (在 Android Studio 中也稱為「模組」),這些子專案也可用做依附元件。每個子專案都會產生輸出內容 (例如 JAR 檔案),供子專案或頂層專案使用。這麼做可以隔離需要重建的部分,並在應用程式中更妥善地分隔責任,進而縮短建構時間。
我們會在「新增建構依附元件」一文中,進一步說明如何指定依附元件。
建構變化版本
建立 Android 應用程式時,通常會建構多個變化版本。變化版本包含不同的程式碼,或使用不同的選項建構,並由建構類型和變種版本組成。
建構類型會變更宣告的建構選項。根據預設,AGP 會設定「發布」和「偵錯」建構類型,但您可以調整這些類型並新增更多類型 (例如用於階段或內部測試)。
偵錯版本不會對應用程式進行精簡或模糊處理,而是加快建構作業並保留所有符號。此外,偵錯版本也會將應用程式標示為「可偵錯」,並使用通用偵錯金鑰簽署應用程式,以及啟用裝置上已安裝應用程式檔案的存取權。這樣一來,您就能在執行應用程式時,探索檔案和資料庫中的已儲存資料。
發布版本會對應用程式進行最佳化,並使用發布金鑰簽署應用程式,以及保護已安裝的應用程式檔案。
您可以使用產品變種版本,變更應用程式的所含來源和依附元件變化版本。舉例來說,您可能想為應用程式建立「試用版」和「完整版」變種版本,或者「免費」和「付費」變種版本。您可以在「main」來源集目錄中編寫常用來源,並在以變種版本命名的來源集中覆寫或新增來源。
AGP 會針對每個建構類型和變種版本組合建立變化版本。如果您未定義變種版本,系統會根據建構類型為變化版本命名。如果您同時定義這兩個值,變化版本的名稱會是 <flavor><Buildtype>
。舉例來說,如果建構類型為 release
和 debug
,變種版本為 demo
和 full
,AGP 會建立變化版本:
demoRelease
demoDebug
fullRelease
fullDebug
後續步驟
您現在已瞭解建構概念,請查看專案中的 Android 建構結構。