在現代 Android 開發作業中,提供小巧、快速且安全的應用程式是基本的使用者期望。Android 建構系統的主要工具是 R8 最佳化工具,這個編譯器會處理無效程式碼和資源移除作業,以縮減應用程式大小、重新命名或縮減程式碼,以及最佳化應用程式。
啟用 R8 是準備發布應用程式的重要步驟,但開發人員必須以「保留規則」的形式提供指引。
閱讀本文後,請觀看 YouTube 上的「成效焦點週」影片,瞭解如何啟用、偵錯及排解 R8 最佳化工具的問題。
為何需要保留規則
之所以需要編寫 Keep 規則,是因為存在核心衝突:R8 是靜態分析工具,但 Android 應用程式通常依賴動態執行模式,例如使用 JNI (Java 原生介面) 反射或呼叫原生程式碼。
R8 會分析直接呼叫,建構「已使用」程式碼的圖表。如果以動態方式存取程式碼,R8 的靜態分析就無法預測,並會將該程式碼識別為「未使用」並移除,導致執行階段當機。
保留規則是針對 R8 編譯器的明確指令,表示:「這個特定類別、方法或欄位是會在執行階段動態存取的進入點。即使找不到直接參照,也必須保留。」
撰寫保留規則的位置
應用程式的自訂保留規則會寫入文字檔。按照慣例,這個檔案的名稱為 proguard-rules.pro,位於應用程式或程式庫模組的根目錄中。然後在模組的 build.gradle.kts 檔案的 release 建構類型中指定這個檔案。
release {
isShrinkResources = true
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}使用正確的預設檔案
getDefaultProguardFile 方法會匯入 Android SDK 提供的預設規則集。如果使用錯誤的檔案,應用程式可能無法獲得最佳化。請務必使用 proguard-android-optimize.txt。這個檔案提供標準 Android 元件的預設保留規則,並啟用 R8 的程式碼最佳化功能。過時的 proguard-android.txt 只提供保留規則,但不會啟用 R8 的最佳化功能。
由於這是嚴重的效能問題,我們將從 Android Studio Narwhal 3 Feature Drop 開始,警告開發人員使用錯誤的檔案。從 Android Gradle 外掛程式 9.0 版開始,我們不再支援過時的 proguard-android.txt 檔案。因此請務必升級至最佳化版本。
如何撰寫保留規則
保留規則主要由三部分組成:
- 選項 ,例如
-keep或-keepclassmembers - 選用修飾符,例如
allowshrinking - 類別規格,定義要比對的程式碼
如需完整語法和範例,請參閱「新增保留規則」指南。
保留規則反模式
瞭解最佳做法很重要,但也要知道反模式。這些反模式通常源自誤解或疑難排解捷徑,可能會對正式版建構的效能造成災難性影響。
全域選項
這些是全域切換開關,絕不應在發布版本中使用,僅適用於暫時偵錯,以找出問題。
使用 -dontotptimize 會有效停用 R8 的效能最佳化功能,導致應用程式變慢。
使用 -dontobfuscate 會停用所有重新命名作業,而使用 -dontshrink 則會關閉無效程式碼移除作業。這兩項全域規則都會增加應用程式大小。
請盡可能避免在正式環境中使用這些全域標記,以提升應用程式使用者體驗的效能。
過於寬鬆的保留規則
如要輕鬆抵銷 R8 的優點,最簡單的方法就是編寫過於寬鬆的保留規則。以下列保留規則為例,這會指示 R8 最佳化工具不要縮減、混淆處理或最佳化這個套件或任何子套件中的任何類別。這會完全抵銷 R8 對整個套件的優點。請改為編寫範圍較窄且具體的保留規則。
-keep class com.example.package.** { *;} // WIDE KEEP RULES CAUSE PROBLEMS反轉運算子 (!)
反轉運算子 (!) 似乎是從規則排除套件的強大方式。但事實並非如此。我們來看看這個例子
-keep class !com.example.my_package.** { *; } // USE WITH CAUTION您可能會認為這項規則是指「不要保留 com.example.package 中的類別」,但實際上是指「保留整個應用程式中不在 com.example.package 中的所有類別、方法和屬性」。如果您感到意外,建議檢查 R8 設定中是否有任何否定。
Android 元件的備援規則
另一個常見錯誤是手動為應用程式的 Activities、Services 或 BroadcastReceivers 新增 Keep 規則。這是不必要的。預設 proguard-android-optimize.txt 檔案已包含相關規則,因此這些標準 Android 元件可直接運作。
此外,許多程式庫都會提供自己的保留規則。因此您不必為這些項目編寫自己的規則。如果使用的程式庫發生 Keep 規則問題,建議與程式庫作者聯絡,瞭解問題所在。
保留規則最佳做法
瞭解不該做的事後,接著來看看最佳做法。
撰寫範圍較窄的保留規則
良好的保留規則應盡可能明確且具體。他們應只保留必要項目,讓 R8 最佳化其他所有項目。
| 規則 | 品質 |
|---|---|
| 低:保留整個套件及其子套件 |
| 低:保留整個類別,可能還是太廣 |
-keepclassmembers class com.example.MyClass {
private java.lang.String secretMessage;
public void onNativeEvent(java.lang.String);
} | 高:只保留特定類別的相關方法和屬性 |
使用共同祖先
您不必為多個不同的資料模型編寫個別的保留規則,只要編寫一項規則,指定通用的基礎類別或介面即可。下列規則會告知 R8 保留實作這個介面的類別成員,且具有高度可擴充性。
# Keep all fields of any class that implements SerializableModel
-keepclassmembers class * implements com.example.models.SerializableModel {
<fields>;
}使用註解指定多個類別
建立自訂註解 (例如 @Serialize),並用來「標記」需要保留欄位的類別。這是另一種簡潔、宣告式且高度可擴充的模式。您也可以為已使用的架構中現有的註解建立 Keep 規則。
# Keep all fields of any class annotated with @Serialize
-keepclassmembers class * {
@com.example.annotations.Serialize <fields>;
}選擇合適的 Keep 選項
保留選項是規則中最重要的一環,選錯可能會導致最佳化功能無故停用。
| 保留選項 | 功能 |
-keep | 防止系統移除或重新命名類別 和宣告中提及的成員 。 |
-keepclassmembers | 防止特定成員遭到移除或重新命名,但允許移除類別本身,但僅限於未以其他方式移除的類別。 |
-keepclasseswithmembers | 組合:保留類別「和」其成員,前提是所有指定成員都存在。 |
如要進一步瞭解保留選項,請參閱保留選項說明文件。
允許使用修飾符進行最佳化
allowshrinking 和 allowobfuscation 等修飾符會放寬廣泛的 -keep 規則,將最佳化功能還給 R8。舉例來說,如果舊版程式庫強制您在整個類別中使用 -keep,您或許可以允許縮減和混淆處理,以回收部分最佳化功能:
# Keep this class, but allow R8 to remove it if it's unused and allow R8 to rename it. -keep,allowshrinking,allowobfuscation class com.example.LegacyClass
新增全域選項,進一步最佳化
除了保留規則,您還可以在 R8 設定檔中新增全域標記,進一步提升最佳化效果。
-repackageclasses 是強大的選項,可指示 R8 將所有經過模糊處理的類別移至單一套件。這樣一來,系統會移除多餘的套件名稱字串,大幅節省 DEX 檔案空間。
-allowaccessmodification 可讓 R8 擴大存取權 (例如 private 至 public),以便啟用更積極的內嵌作業。使用 proguard-android-optimize.txt 時,這項功能現在預設為啟用。
警告:程式庫作者絕不能將這些全域最佳化標記新增至消費者規則,因為這些標記會強制套用至整個應用程式。
為進一步釐清,Android Gradle 外掛程式 9.0 版將完全忽略程式庫的整體最佳化標記。
程式庫最佳做法
每個 Android 應用程式都會以某種方式依附程式庫。因此,我們來談談程式庫的最佳做法。
程式庫開發人員
如果程式庫使用反射或 JNI,您有責任為消費者提供必要的保留規則。這些規則會放在 consumer-rules.pro 檔案中,然後自動與程式庫的 AAR 檔案綁在一起。
android {
defaultConfig {
consumerProguardFiles("consumer-rules.pro")
}
...
}程式庫消費者
篩除有問題的保留規則
如果必須使用包含有問題的保留規則的程式庫,可以從 AGP 9.0 開始,在 build.gradle.kts 檔案中篩除這些規則。這樣一來,R8 就會忽略來自特定依附元件的規則。
release {
optimization.keepRules {
// Ignore all consumer rules from this specific library
it.ignoreFrom("com.somelibrary:somelibrary")
}
}最佳的 Keep 規則就是沒有 Keep 規則
最終的 R8 設定策略是完全不需要編寫保留規則。許多應用程式可以選擇偏好程式碼產生而非反射的現代程式庫,達成這個目標。透過程式碼產生,最佳化工具可以更輕鬆地判斷執行階段實際使用的程式碼,以及可以移除的程式碼。此外,不使用任何動態反射表示沒有「隱藏」的進入點,因此不需要保留規則。選擇新程式庫時,請一律優先採用使用程式碼產生而非反射的解決方案。
如要進一步瞭解如何選擇程式庫,請參閱「明智地選擇程式庫」。
偵錯及排解 R8 設定問題
如果 R8 移除了應該保留的程式碼,或是 APK 大小超出預期,請使用這些工具診斷問題。
找出重複和全域的 Keep 規則
由於 R8 會合併數十個來源的規則,因此很難知道「最終」規則集為何。在 proguard-rules.pro 檔案中加入這個標記,即可產生完整報表:
# Outputs the final, merged set of rules to the specified file -printconfiguration build/outputs/logs/configuration.txt
您可以搜尋這個檔案,找出多餘的規則,或將有問題的規則 (例如 -dontoptimize) 追溯至包含該規則的特定程式庫。
詢問 R8:為什麼要保留這個?
如果預期要移除的類別仍在應用程式中,R8 可以告訴您原因。只要新增這項規則即可:
# Asks R8 to explain why it's keeping a specific class class com.example.MyUnusedClass -whyareyoukeeping
建構期間,R8 會列印導致保留該類別的確切參照鏈結,方便您追蹤參照並調整規則。
如需完整指南,請參閱「排解 R8 問題」一節。
後續步驟
R8 是提升 Android 應用程式效能的強大工具,但能否有效發揮作用,取決於您是否正確瞭解其靜態分析引擎的運作方式。
撰寫特定成員層級的規則、善用祖先和註解,並謹慎選擇合適的保留選項,即可保留必要內容。最先進的做法是選擇以程式碼生成為基礎的現代程式庫,取代以反射為基礎的舊版程式庫,完全不需要規則。
在「成效焦點週」期間,請務必觀看 YouTube 上的焦點週影片,並繼續參加 R8 挑戰。如有啟用或排解 R8 相關問題,請使用 #optimizationEnabled。我們很樂意提供協助。
現在就來親身體驗這些優點吧!
我們誠摯邀請您立即為應用程式啟用 R8 完整模式。
- 請參閱開發人員指南,瞭解如何啟用應用程式最佳化功能。
- 檢查您是否仍使用
proguard-android.txt,並將其替換為proguard-android-optimize.txt。 - 接著,請評估成效。不要只是「感覺」有差異,請「驗證」差異。如要評估效能提升幅度,請改編 GitHub 上的 Macrobenchmark 範例應用程式程式碼,測量前後的啟動時間。
我們相信應用程式效能會大幅提升。
歡迎使用社群媒體標記 #AskAndroid 提出問題。在整個活動週期間,我們的專家都會監看並回答您的問題。
敬請期待明天的內容,我們將討論以設定檔為導向的最佳化功能,包括基準和啟動設定檔,分享 Compose 在過去版本中改善的算繪效能,以及背景作業的效能考量。
繼續閱讀
-
產品新訊
從擴增疊加層到完全沉浸式環境,Android XR 生態系統正在迅速擴展,Samsung Galaxy XR 也已於今天上市。
Stevan Silva, Vinny DaSilva • 3 分鐘可讀完
-
產品新訊
每年 Google I/O 大會都會發布生態系統和產品的最新消息與資源,包括 Android 開發。隨著開發工作轉向 AI 和代理程式輔助工具,我們也擴大產品陣容,無論您決定如何建構 Android 應用程式,都能獲得更完善的支援。
Simona Milanovic • 閱讀時間:2 分鐘
-
產品新訊
在 2026 年 Google I/O 大會上,我們展示了 Android 生態系統的最新進展,說明如何協助您提升應用程式品質,同時盡可能提高開發效率。
Ataul Munim • 3 分鐘可讀完
隨時掌握最新消息
每週透過電子郵件接收最新的 Android 開發洞察資訊。