Wenn Sie die App-Optimierung aktivieren möchten, müssen Sie Bibliotheken verwenden, die mit der Android-Optimierung kompatibel sind. Wenn eine Bibliothek nicht für die Android-Optimierung konfiguriert ist, z. B. wenn sie Reflexion ohne Bündelung zugehöriger Keep-Regeln verwendet, ist sie möglicherweise nicht gut für eine Android-App geeignet. Auf dieser Seite wird erläutert, warum einige Bibliotheken besser für die App-Optimierung geeignet sind, und es werden allgemeine Tipps zur Auswahl gegeben.
Allgemeine Tipps zur Auswahl von Bibliotheken
Mit diesen Tipps können Sie sicherstellen, dass Ihre Bibliotheken mit der App-Optimierung kompatibel sind.
Codegen gegenüber Reflexion bevorzugen
Wählen Sie Bibliotheken aus, die Codegenerierung (codegen) anstelle von Reflexion verwenden. Mit Codegen kann der Optimizer ermitteln, welcher Code zur Laufzeit tatsächlich verwendet wird und welcher Code entfernt werden kann. Es ist möglicherweise schwierig zu erkennen, ob eine Bibliothek Codegen oder Reflexion verwendet. Es gibt jedoch einige Anzeichen. Weitere Informationen finden Sie in den Tipps.
Weitere Informationen zu Codegen im Vergleich zu Reflexion finden Sie unter Optimierung für Bibliotheksautoren.
Auf Verwendung von Reflexion prüfen (erweitert)
Sie können anhand des Codes einer Bibliothek erkennen, ob sie Reflexion verwendet. Wenn die Bibliothek Reflexion verwendet, prüfen Sie, ob sie zugehörige Keep-Regeln enthält. Eine Bibliothek verwendet wahrscheinlich Reflexion, wenn sie Folgendes tut:
- Verwendet Klassen oder Methoden aus den Paketen
kotlin.reflectoderjava.lang.reflect. - Verwendet die Funktionen
Class.forNameoderclassLoader.getClass. - Liest Anmerkungen zur Laufzeit, z. B. wenn ein Anmerkungswert
mit
val value = myClass.getAnnotation()oderval value = myMethod.getAnnotation()gespeichert wird und dann etwas mitvaluegeschieht. Ruft Methoden mit dem Methodennamen als String auf, wie im folgenden Beispiel:
// Calls the private `processData` API with reflection myObject.javaClass.getMethod("processData", DataType::class.java) ?.invoke(myObject, data)
Auf Optimierungsprobleme prüfen
Wenn Sie eine neue Bibliothek in Betracht ziehen, sehen Sie sich den Issue-Tracker und die Online-Diskussionen der Bibliothek an, um zu prüfen, ob es Probleme im Zusammenhang mit der Minimierung oder der Konfiguration der App-Optimierung gibt. Wenn dies der Fall ist, sollten Sie nach Alternativen zu dieser Bibliothek suchen. Beachten Sie dabei Folgendes:
- Die AndroidX-Bibliotheken und Bibliotheken wie Hilt eignen sich gut für die App-Optimierung, da sie hauptsächlich Codegen anstelle von Reflexion verwenden. Wenn sie Reflexion verwenden, stellen sie minimale Keep-Regeln bereit, um nur den benötigten Code beizubehalten.
- Serialisierungsbibliotheken verwenden häufig Reflexion, um Boilerplate-Code beim Instanziieren oder Serialisieren von Objekten zu vermeiden. Suchen Sie anstelle von reflexionsbasierten Ansätzen (z. B. Gson für JSON) nach Bibliotheken, die Codegen verwenden, um diese Probleme zu vermeiden, z. B. mit Kotlin Serialization {:.external} oder Moshi mit Codegen.
- Vermeiden Sie nach Möglichkeit Bibliotheken, die paketweite Keep-Regeln enthalten. Paketweite Keep-Regeln können helfen, Fehler zu beheben. Breite Keep-Regeln sollten jedoch letztendlich verfeinert werden, um nur den benötigten Code beizubehalten. Weitere Informationen finden Sie unter Optimierungen schrittweise übernehmen.
- Bevor Sie eine App veröffentlichen, die eine Drittanbieterbibliothek verwendet, prüfen Sie die bereitgestellten Keep-Regeln mit dem R8 Konfigurationsanalysetool. Anhand des Berichts können Sie prüfen, ob die Keep-Regeln der Bibliothek zu breit gefasst sind und verhindern, dass R8 wichtige Optimierungen an Ihrer Codebasis vornimmt. Mit dieser Prüfung wird sichergestellt, dass die ausgewählten Bibliotheken den Leistungszielen Ihrer App entsprechen und keine unnötige Konfigurationsaufblähung verursachen.
- Bibliotheken sollten nicht erfordern, dass Sie Keep-Regeln aus der Dokumentation kopieren und in eine Datei in Ihrem Projekt einfügen, insbesondere nicht paketweite Keep-Regeln. Diese Regeln stellen langfristig eine Wartungslast für den App-Entwickler dar und sind im Laufe der Zeit schwer zu optimieren und zu ändern.
Optimierung nach dem Hinzufügen einer neuen Bibliothek aktivieren
Wenn Sie eine neue Bibliothek hinzufügen, aktivieren Sie die Optimierung anschließend und prüfen Sie, ob Fehler auftreten. Wenn Fehler auftreten, suchen Sie nach Alternativen zu dieser Bibliothek oder schreiben Sie Keep-Regeln. Wenn eine Bibliothek nicht mit der Optimierung kompatibel ist, melden Sie einen Fehler für diese Bibliothek.
Schlechte Keep-Regeln herausfiltern (erweitert)
Keep-Regeln werden addiert. Das bedeutet, dass bestimmte Regeln, die eine Bibliotheksabhängigkeit enthält, nicht entfernt werden können und sich auf die Kompilierung anderer Teile Ihrer App auswirken können. Wenn eine Bibliothek beispielsweise eine Regel zum Deaktivieren von Codeoptimierungen enthält, werden Optimierungen für Ihr gesamtes Projekt deaktiviert.
Sie sollten Bibliotheken mit Keep-Regeln vermeiden, die Code beibehalten, der eigentlich entfernt werden sollte. Wenn Sie sie jedoch verwenden müssen, können Sie die Regeln herausfiltern, wie im folgenden Code gezeigt:
// If you're using AGP 8.4 and higher
buildTypes {
release {
optimization.keepRules {
it.ignoreFrom("com.somelibrary:somelibrary")
}
}
}
// If you're using AGP 7.3-8.3
buildTypes {
release {
optimization.keepRules {
it.ignoreExternalDependencies("com.somelibrary:somelibrary")
}
}
}
Fallstudie: Warum Gson bei Optimierungen Probleme verursacht
Gson ist eine Serialisierungsbibliothek, die häufig Probleme bei der App-Optimierung verursacht, da sie stark auf Reflexion setzt. Das folgende Code-Snippet zeigt, wie Gson normalerweise verwendet wird, was zu Abstürzen zur Laufzeit führen kann. Wenn Sie mit Gson eine Liste von User-Objekten abrufen, rufen Sie den Konstruktor nicht auf und übergeben keine Factory an die Funktion fromJson(). Das Erstellen oder Verwenden von von der App definierten Klassen ohne eine der folgenden Optionen ist ein Zeichen dafür, dass eine Bibliothek möglicherweise eine offene Reflexion verwendet:
- App-Klasse, die eine Bibliothek oder eine Standardschnittstelle oder -klasse implementiert
- Codegenerierungs-Plug-in wie KSP
class User(val name: String)
class UserList(val users: List<User>)
// This code runs in debug mode, but crashes when optimizations are enabled
Gson().fromJson("""[{"name":"myname"}]""", User::class.java).toString()
Informationen zur Funktionsweise von R8 mit Gson finden Sie unter den Gson-Consumer-Regeln. Wenn R8
diesen Code analysiert und nicht sieht, dass UserList oder User irgendwo instanziiert
werden, kann es Felder umbenennen oder Konstruktoren entfernen, die nicht verwendet zu werden scheinen
, was zum Absturz Ihrer App führt. Wenn Sie andere Bibliotheken auf ähnliche Weise verwenden, sollten Sie prüfen, ob sie die App-Optimierung beeinträchtigen. Wenn dies der Fall ist, sollten Sie sie vermeiden.
@SerializedName mit späteren Gson-Versionen verwenden
Wenn Sie Ihre Datenmodelle so definieren möchten, dass sie mit den Consumer-Regeln von Gson kompatibel sind, versehen Sie Ihre Felder mit der Annotation @SerializedName, wie im folgenden Snippet gezeigt:
import com.google.gson.annotations.SerializedName
class User(@SerializedName("name") val name: String)
class UserList(@SerializedName("users") val users: List<User>)
Mit der @SerializedName Annotation können Sie R8 Ihre Modell
klassen mit den Keep-Regeln abgleichen, die in Gson Version 2.11.0 und höher enthalten sind.
R8 behält die mit Annotationen versehenen Felder und erforderlichen Konstruktoren automatisch bei, sodass Sie sich auf die in der Bibliothek enthaltenen Regeln verlassen können, ohne manuelle ProGuard-Konfigurationen in Ihrem Projekt verwalten zu müssen.
Beachten Sie, dass Room, Hilt und Moshi mit Codegen von der App definierte Typen erstellen , aber Codegen verwenden, um Reflexion zu vermeiden.