Android 應用程式通常是使用 Gradle 建構系統建構。在深入探討如何設定建構作業之前,我們會先說明建構作業背後的概念,讓您瞭解整個系統。
什麼是建構作業?
建構系統會將原始碼轉換為可執行的應用程式。建構作業通常涉及多項工具,用於分析、編譯、連結及封裝應用程式或程式庫。Gradle 會採用工作導向的方法,整理及執行這些指令。
工作會封裝指令,將輸入內容轉譯為輸出內容。外掛程式會定義工作和設定。將外掛程式套用至建構作業,即可註冊工作,並使用輸入和輸出內容將工作連結在一起。舉例來說,將 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 { version = release(36) { minorApiLevel = 1 } } // ... defaultConfig { applicationId = "com.example.app" minSdk { version = release(23) } targetSdk { version = release(36) } // ... } }
Groovy
android { namespace = 'com.example.app' compileSdk { version = release(36) { minorApiLevel = 1 } } // ... defaultConfig { applicationId = 'com.example.app' minSdk { version = release(23) } targetSdk { version = release(36) } // ... } }
在幕後,DSL 程式碼類似於:
fun Project.android(configure: ApplicationExtension.() -> Unit) {
...
}
interface ApplicationExtension {
var namespace: String?
fun compileSdk(configure: CompileSdkSpec.() -> Unit) {
...
}
val defaultConfig: DefaultConfig
fun defaultConfig(configure: DefaultConfig.() -> Unit) {
...
}
}
DSL 中的每個區塊都由一個函式表示,該函式會使用 lambda 進行設定,並使用同名屬性進行存取。這會讓建構檔案中的程式碼更像資料規格。
外部依附元件
Maven 建構系統導入了依附元件規格、儲存和管理系統。程式庫儲存在存放區 (伺服器或目錄) 中,中繼資料包括版本和對其他程式庫的依附元件。您需要指定要搜尋的存放區、要使用的依附元件版本,建構系統會在建構期間下載這些元件。
Maven 成果會依群組名稱 (公司、開發人員等)、成果名稱 (程式庫名稱) 和成果版本來識別。通常以 group:artifact:version 表示。
這種做法可大幅改善建構管理。您通常會聽到這類存放區稱為「Maven 存放區」,但這與構件的封裝和發布方式有關。這些存放區和中繼資料已在多個建構系統中重複使用,包括 Gradle (Gradle 可發布至這些存放區)。公開存放區可供所有人共用,公司存放區則可保留內部依附元件。
您也可以將專案模組化為子專案 (在 Android Studio 中也稱為「模組」),這些子專案也可以做為依附元件。每個子專案都會產生輸出內容 (例如 jar),可供子專案或頂層專案使用。這樣可以隔離需要重新建構的部分,縮短建構時間,並更妥善地劃分應用程式中的責任。
我們會在「新增建構依附元件」一節中,進一步說明如何指定依附元件。
建構變化版本
建立 Android 應用程式時,通常會想建構多個變化版本。變化版本包含不同的程式碼,或使用不同的選項建構,並由建構類型和變種版本組成。
建構類型會因宣告的建構選項而異。根據預設,AGP 會設定「release」和「debug」建構類型,但您可以調整這些類型並新增更多類型 (例如用於測試或內部測試)。
偵錯版本不會壓縮或模糊處理應用程式,因此可加快建構速度,並保留所有符號。此外,偵錯版本也會將應用程式標示為「可進行偵錯」,並使用一般偵錯金鑰簽署,以及啟用裝置上已安裝應用程式檔案的存取權。這樣一來,您就能在執行應用程式時,探索檔案和資料庫中儲存的資料。
發布子版本會最佳化應用程式、使用發布金鑰簽署,並保護已安裝的應用程式檔案。
您可以使用產品變種版本,變更應用程式包含的來源和依附元件變化版本。舉例來說,您可能想為應用程式建立「demo」和「full」版本,或「free」和「paid」版本。您可以在「main」來源集目錄中編寫通用來源,並在以變種版本命名的來源集中覆寫或新增來源。
AGP 會為建構類型和變種版本的每種組合建立變化版本。如未定義變種版本,則會根據建構類型命名。如果兩者都定義,變化版本會命名為 <flavor><Buildtype>。舉例來說,如果建構類型為 release 和 debug,變種版本為 demo 和 full,AGP 會建立以下變化版本:
demoReleasedemoDebugfullReleasefullDebug
後續步驟
瞭解建構概念後,請查看專案中的 Android 建構結構。