使用預設設定啟用應用程式最佳化時,R8 會執行廣泛的最佳化,盡可能提升效能。R8 會大幅修改程式碼,包括重新命名、移動及移除類別、欄位和方法。如果發現這些修改造成錯誤,您必須在保留規則中宣告 R8「不應」修改程式碼的哪些部分。
需要保留規則的常見情境
R8 會識別並保留程式碼中的所有直接呼叫。不過,R8 無法查看間接程式碼的使用情形,因此可能會移除應用程式所需的程式碼,導致當機。請使用保留規則,指示 R8 保留這類間接使用的程式碼。以下是可能需要保留規則的幾種常見情況:
- 透過反射存取的程式碼:R8 無法識別透過反射存取的類別、欄位或方法。舉例來說,R8 無法識別使用
Class.getDeclaredMethod()依名稱查詢的方法,或使用Class.getAnnotation()擷取的註解。在這種情況下,R8 可能會重新命名這些方法和註解,或將其完全移除,導致在執行階段發生ClassNotFoundException或NoSuchMethodException。 - 從 Java Native Interface (JNI) 呼叫的程式碼:當原生 (C 或 C++) 程式碼呼叫 Java 或 Kotlin 方法,或 Java 或 Kotlin 程式碼使用 JNI 呼叫 C++ 程式碼時,呼叫會根據方法名稱的動態字串查詢。R8 無法查看動態字串型方法呼叫,因此最佳化作業可能會破壞程式碼。
這份清單並未列出所有需要保留規則的情境,但已涵蓋大部分可能需要保留規則的情況。
如果您的程式碼使用反射或從 JNI 呼叫,您可以使用 Jetpack Keep 註解,而不必手動編寫保留規則。其 Gradle 外掛程式會在建構時,根據註解產生保留規則。
瞭解保留規則對最佳化的影響
R8 是全程式最佳化工具,可分析應用程式程式碼,移除未使用的程式碼、內嵌方法、合併類別,以及模糊處理 ID。不過,R8 只能在您定義的設定範圍內進行最佳化。
保留規則代表明確限制最佳化的指令。您宣告的每項保留規則都會限制 R8 轉換程式碼集該部分的能力。精心設計的保留規則,價值在於其具體性:
縮小保留規則範圍,盡可能提高最佳化效果:只指定動態存取的確切進入點 (例如反射建構函式或序列化欄位),讓 R8 最佳化其餘程式碼。
廣泛的保留規則會阻礙最佳化:宣告套件範圍規則或廣泛的萬用字元,會導致 R8 無法最佳化整個類別及其所有成員。R8 無法移除、內嵌、合併或模糊處理該程式碼。
如果保留規則過於廣泛,會直接導致 DEX 二進位檔過於龐大、應用程式記憶體用量增加、啟動時間變慢 (TTID 和 TTFD),以及 ANR 發生率提高。您的目標不應是保留類別「以防萬一」,而是定義動態執行所需的最小合約。
如要找出廣泛或不必要的保留規則 (包括來自第三方資料庫的規則),請使用 R8 設定分析器。這份報告會顯示縮減、最佳化和模糊處理分數,指出 R8 可最佳化的程式碼量。
如何在應用程式中新增保留規則
保留規則設定取決於您使用的 AGP 版本。
大型應用程式通常會將程式碼分散在多個程式庫模組中。在這種情況下,最好將保留規則與適用的程式碼一併放在特定程式庫模組中。維護程式庫保留規則的重要差異,在於如何在程式庫模組的 build.gradle.kts (或 build.gradle) 檔案中宣告這些規則。詳情請參閱「程式庫作者最佳化」。
適用於 AGP 9.3 以上版本
在 src/<variant>/keepRules 目錄中,將規則新增至後置字串為 .keep 的檔案。例如:src/main/keepRules/custom-rules.keep。請注意,使用 AGP 9.3 以上版本的更新 DSL,可同時啟用程式碼和資源最佳化,且不需要明確定義預設的 Android 保留規則檔案 (proguard-android-optimize.txt),因為系統預設會包含該檔案,除非明確省略。
Kotlin
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
}
Groovy
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
}
省略預設 Android 平台保留規則 (進階)
AGP 提供一組預設的 Android 平台規則。如要從專案設定中省略這些規則,並自行管理所有保留規則,請將 optimization.keepRules.includeDefault 設為 false。
Kotlin
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
keepRules {
includeDefault = false // The file with optimization
// rules for the Android platform is included by
// default. To omit this file, set this option to false.
}
}
}
}
}
Groovy
android {
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
keepRules {
includeDefault = false // The file with optimization
// rules for the Android platform is included by
// default. To omit this file, set this option to false.
}
}
}
}
}
9.3 以下 AGP 版本的舊版 DSL
請將規則新增至位於應用程式模組根目錄中的 proguard-rules.pro 檔案。該檔案可能已存在,但如果不存在,請建立該檔案。如要套用檔案中的規則,您必須在模組層級 build.gradle.kts (或 build.gradle) 檔案中宣告該檔案。
根據預設,建構檔案也會包含 proguard-android-optimize.txt 檔案。這個檔案包含大多數 Android 專案所需的規則,因此請保留在建構檔案中。這個檔案是以 proguard-common.txt 檔案為基礎,並與該檔案共用內容。
舊版 DSL (Kotlin)
android {
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
// Default file with default optimization rules.
getDefaultProguardFile("proguard-android-optimize.txt"),
...
)
}
}
}
舊版 DSL (Groovy)
android {
buildTypes {
release {
minifyEnabled = true
shrinkResources = true
// Default file with default optimization rules.
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
...
}
}
}
新增保留規則
新增保留規則時,您可以加入全域選項,也可以定義自己的保留規則。
全域選項:全域選項是一般指令,會影響 R8 在整個程式碼集上的運作方式。詳情請參閱「全域選項」。
保留規則:請務必謹慎設計保留規則,確保在盡可能最佳化程式碼和避免不小心破壞應用程式之間取得適當平衡。如要瞭解如何編寫保留規則,請參閱「新增保留規則」。
程式庫作者的保留規則
瞭解保留規則的全域選項和語法後,請參閱「程式庫作者最佳化」一文,瞭解更多詳細資料。